C++ 模板中包含自定义类似编译问题

    技术2024-06-20  70

     

    这里的一个模板类里定义了一个函数指针。代码如下:

     

    template<typename Tin, typename Tout>   class CAbstractTask : public IExecutable<Tin, Tout> {   public:     typedef uint32_t (CAbstractTask<Tin, Tout>::* Delegate)(const Tin& pContext, Tout& oFuture);

       public:     CAbstractTask();

         virtual ~CAbstractTask();

       public:

     

    /**其它的省略**/

         //获取委派     virtual Delegate Dispatch(const std::string& sName);

       private:     std::map<std::string, Delegate> m_mapDelegate;   };

    //定义   template<typename Tin, typename Tout>   CAbstractTask<Tin, Tout>::Delegate CAbstractTask<Tin, Tout>::Dispatch(const std::string& sName)   {     std::map<std::string, Delegate>::const_iterator rFound = m_mapDelegate.find(sName);      if ( rFound != m_mapDelegate.end() ) {      return rFound->second;     }

         return NULL;   }

     

     

    这段代码看上去没什么问题,但是在g++环境下编译不过:

    abstract_task.h:89: error: expected constructor, destructor, or type conversion before 'CAbstractTask'

     

    在此行起始处添加typename关键字。

    typename  CAbstractTask<Tin, Tout>::Delegate CAbstractTask<Tin, Tout>::Dispatch(const std::string& sName)

    编译后得到如下结果:

    abstract_task.h:91: error: expected `;' before 'rFound'

    abstract_task.h:92: error: 'rFound' was not declared in this scope

     

    再在申明的地方加了typename关键字。

    typename std::map<std::string, Delegate>::const_iterator rFound = m_mapDelegate.find(sName);

    这里编译Ok.

     

    查看Google,得到如下说明:

    摘抄原文如下( 查看原文 ):

    [35.18] Why am I getting errors when my template-derived-class uses a nested type it inherits from its template-base-class?

    Perhaps surprisingly, the following code is not valid C++, even though some compilers accept it: 01template<typename T> 02class B { 03public: 04  class Xyz { ... };  // type nested in class B<T> 05  typedef int Pqr;    // type nested in class B<T> 06}; 07template<typename T> 08class D : public B<T> { 09public: 10  void g() 11  { 12    Xyz x;   // bad (even though some compilers erroneously (temporarily?) accept it) 13    Pqr y;   // bad (even though some compilers erroneously (temporarily?) accept it) 14  } 15}; This might hurt your head; better if you sit down. Within D<T>::g(),  name Xyz and Pqr do not depend on template parameter T,  so they are known as a nondependent names. On the other hand, B<T> is dependent on template parameter T so B<T> is called a dependent name. Here’s the rule: the compiler does not look in dependent base classes (like B<T>) when looking up nondependent names (like Xyz or Pqr). As a result, the compiler does not know they even exist let alone are types. At this point, programmers sometimes prefix them with B<T>::, such as: 1template <typename T> 2class D : public B<T> { 3public: 4  void g() 5  { 6    B<T>::Xyz x;  // bad (even though some compilers erroneously (temporarily?) accept it) 7    B<T>::Pqr y;  // bad (even though some compilers erroneously (temporarily?) accept it) 8  } 9}; Unfortunately this doesn’t work either because those names (are you ready? are you sitting down?) are not necessarily types. “Huh?!?” you say. “Not types?!?” you exclaim. “That’s crazy; any fool can SEE they are types; just look!!!” you protest. Sorry, the fact is that they might not be types. The reason is that there can be a specialization of B<T>, say B<Foo>, where B<Foo>::Xyz is a data member, for example. Because of this potential specialization, the compiler cannot assume that B<T>::Xyz is a type until it knows T. The solution is to give the compiler a hint via the typename keyword: 1template<typename T> 2class D : public B<T> { 3public: 4  void g() 5  { 6    typename B<T>::Xyz x;  // good 7    typename B<T>::Pqr y;  // good 8  } 9};  

     

     

     

     

     

    最新回复(0)