Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

probleme avec les templates et heritage

1 réponse
Avatar
thierry nivon
Bonjour,
j'ai un problème avec une utilisation des templates dans le header suivant.
En fait il s'agit en fin de header des instructions

NeedLock=false ;
Splitter=new TSplitter() ;

gcc me retourne
/home/tn/dev-perso/tnutils/trunk/tnutils/src/../include/tnserial.h:190:
erreur: ‘NeedLock’ was not declared in this scope
/home/tn/dev-perso/tnutils/trunk/tnutils/src/../include/tnserial.h:191:
erreur: ‘Splitter’ was not declared in this scope
gmake[2]: *** [include/CMakeFiles/tnserial.dir/tnserial.o] Erreur 1

or ces données sont dans l'ancetre de CSerialPortTdSplitter et même en
public.

Je n'arrie pas à comprendre où est le problème.

Si qq'un a une piste (voire la solution !)

Thierry

#ifndef _TNSERIAL_H_
#define _TNSERIAL_H_

#include <tnpthread.h>
#include <SerialPort.h>
#include <list>


class CSerialPortSplitter ;

/** @brief extends SerialPort by adding to it threaded reading.

A thread will read data from com port and put it in buffer.\n
It can also have a parser wich will create chars segment
corresponding to a message

*/
class CSerialPortTdBas : public SerialPort
{
private:
typedef SerialPort _ancestor_ ;
typedef std::list<char *> TSplitList ;

CSerialPortTdBas(const CSerialPortTdBas &) ;
const CSerialPortTdBas &operator=(const CSerialPortTdBas&) ;

typedef pthd::CPEmbeddedThread<CSerialPortTdBas> TSerialThread ;
TSerialThread *SerialThread ;

protected:
char *InputBuffer ;
int InputBufferSize ,
InputBufferCount ;
TSplitList SplitList ;

pthread_mutex_t *BuffMutex ;

//! In case of too many frame waiting to be read drop the oldest one
void DropFirstFrame() { free(GetFrame()) ; }


public:
CSerialPortTdBas(std::string &_SerialPort) ;
virtual ~CSerialPortTdBas() ;

// Pour l'instant ici
//! @todo revoir les templates
CSerialPortSplitter *Splitter ;
bool NeedLock ;

int ExecuteThread(pthd::CPThread *Thread) ;

/** Default time out when waiting for a char */
int TimeOut ;
/** Max number of frame splitted and waiting to be read. When a new
frame arrive
and the number of waiting frame has reached this number, the
oldest one will be dropped
*/
unsigned int MaxFrameCount ;

/** Start to read the serial port and feeding InputBuffer
*/
void StartSerialRead() ;

void LockData() { pthread_mutex_lock(BuffMutex) ; }
void UnlockData() { pthread_mutex_unlock(BuffMutex) ; }

/** @return the number of accumlated frames in the list
*/
unsigned int FrameCount() const { return SplitList.size() ; }

/** @return return the first frame in the list, and remove it from
the list.
Return NULL if no frame is present in the list
*/
char *GetFrame() ;
} ;


/** @brief A buffer with a defined buffer

This is a usable Serial Port, as its ancestor as no buffer to store
incoming data,
so thread is useless
*/
template <int BuffSize>
class CSerialPortTdBuff : public CSerialPortTdBas
{
private:
typedef CSerialPortTdBas _ancestor_ ;
CSerialPortTdBuff(const CSerialPortTdBuff&) ;
const CSerialPortTdBuff & operator=(const CSerialPortTdBuff&) ;


public:
CSerialPortTdBuff(std::string &_SerialPort) ;
} ;

template <class TSplitter, int BuffSize>
class CSerialPortTdSplitter : public CSerialPortTdBuff<BuffSize>
{
private:
typedef CSerialPortTdBuff<BuffSize> _ancestor_ ;

CSerialPortTdSplitter(const CSerialPortTdSplitter&) ;
const CSerialPortTdSplitter &operator=(const CSerialPortTdSplitter&) ;

public:
CSerialPortTdSplitter(std::string &_SerialPort) ;

} ;

/** @brief The basic splitter

Try to find a frame in a buffer. There is several manner to split a
frame :
- Identified beginning and end chars
- Only end chars (CR or LF, or CRLF, by example)
- Only a start char, and fixed length
- ...

When trying to split several case can be found :
- we find the beginning of a frame, but not the end --> To not
overflow the buffer it can be right to
move the beginning of the from on the beginning of the buffer, to
make place of the rest of incoming frame -->
We would return @em saClearUntilBeg and SplitStart to the position
of the beginning of frame, or @em saNothing
if the beginning of the frame is already at the fist position in buffer.
- We can not find no frame start --> We could return @em saClearAll
- We find a frame --> we must return @em saMakeSplit with SplitStart
and SplitEnd on the start and end of frame
-

*/
class CSerialPortSplitter
{
private:
CSerialPortSplitter(const CSerialPortSplitter&) ;
const CSerialPortSplitter &operator=(const CSerialPortSplitter&) ;

public:
CSerialPortSplitter() ;
virtual ~CSerialPortSplitter() ;

//! The action to do after splitting
enum ESplitAction {
saNothing, //!< Nothing to do
saClearUntilBeg, //!< A beginning of frame has
been found, so we must clear until beginning
saClearAll, //!< Nothing found in the buffer, so
clear all
saMakeSplit //!< A frame has been found, so we
extract it and put it in the split list
} ;


/** Try to find a frame in the buffer, and return what action to do
after analyzis
* @param _Buffer The buffer where to search a frame
* @param _BufferCount the buffer length
* @param SplitStart the beginning of the frame.
* @param SplitEnd the end of the frame
* @return The action to do.
*/
virtual ESplitAction Split(const char *_Buffer, const int
_BufferCount, int *SplitStart, int *SplitEnd) = 0 ;

} ;

template <int BuffSize>
CSerialPortTdBuff<BuffSize>::CSerialPortTdBuff(std::string &_SerialPort) :
_ancestor_(_SerialPort)
{
InputBuffer=(char *) malloc(BuffSize) ;
InputBufferSize=BuffSize ;
}

template <class TSplitter, int BuffSize>
CSerialPortTdSplitter<TSplitter,
BuffSize>::CSerialPortTdSplitter(std::string &_SerialPort) :
_ancestor_(_SerialPort)
{
NeedLock=false ;
// CSerialPortTdBas::Splitter=new TSplitter() ;
}

#endif // _TNSERIAL_H_

1 réponse

Avatar
Franck Branjonneau
(Pour une prochaine fois : réduit ton code à un minimum compilable -- modulo
l'erreur)

thierry nivon écrivait:

j'ai un problème avec une utilisation des templates dans le header suivant.
Je n'arrie pas à comprendre où est le problème.

Si qq'un a une piste (voire la solution !)


Tu as *en résumé* une classe template B qui hérite d'une classe template A et
qui tente dans une fonction membre B::foo d'accéder à un membre de A.

template< int >
struct A:

int member_;
};

template< int i >
struct B:
public A< i > {

int
foo() {
return member_;
}
} ;

Le problème est que dans B::foo, le symbole member_ n'est pas dépendant. Il
est donc cherché dans la premier temps de la compilation du template. En
particulier le compilateur ne le cherche pas dans la classe template hérité
A< i >.

La solution est de rendre member_ dépendant :

int
foo() {
return A< i >::member_;
}

ou (je crois que c'est la solution la plus prisée)

int
foo() {
return this->member_;
}


ou enfin en utilisant une « using déclaration » (de préférence au niveau de la
classe)

template< int i >
struct B:
public A< i > {

using A< i >::member_;

int
foo() {
return member_;
}
} ;

Toutes ont des avantages et des inconvénients.

--
Boujou
Franck