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

 

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

 

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};
 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值