【问题标题】:C++ template-function -> passing a template-class as template-argumentC ++模板函数->将模板类作为模板参数传递
【发布时间】:2010-06-02 09:32:47
【问题描述】:

我尝试大量使用模板来包装工厂类:

包装类(即classA)通过模板参数获取包装类(即classB)以提供“可插拔性”。

此外,我必须提供一个从包装的内部类 (innerB) 继承的内部类 (innerA)。

问题是g++“gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)”的以下错误信息:

sebastian@tecuhtli:~/Development/cppExercises/functionTemplate$ g++ -o test test.cpp
test.cpp: In static member function ‘static classA<A>::innerA<iB>* classA<A>::createInnerAs(iB&) [with iB = int, A = classB]’:
test.cpp:39:   instantiated from here
test.cpp:32: error: dependent-name ‘classA::innerA<>’ is parsed as a non-type, but instantiation yields a type
test.cpp:32: note: say ‘typename classA::innerA<>’ if a type is meant

正如您在方法 createInnerBs 的定义中看到的,我打算传递一个非类型参数。所以typename的使用是错误的!

test.cpp的代码如下:

class classB{
public:
  template < class iB>
  class innerB{
    iB& ib;
    innerB(iB& b)
      :ib(b){}
  };

  template<template <class> class classShell, class iB>
  static classShell<iB>* createInnerBs(iB& b){
    // this function creates instances of innerB and its subclasses, 
    // because B holds a certain allocator

    return new classShell<iB>(b);
  }  
};

template<class A>
class classA{
  // intention of this class is meant to be a pluggable interface
  // using templates for compile-time checking
public:
  template <class iB>
  class innerA: A::template innerB<iB>{
    innerA(iB& b)
      :A::template innerB<iB>(b){}
  };

  template<class iB>
  static inline innerA<iB>* createInnerAs(iB& b){
    return A::createInnerBs<classA<A>::template innerA<> >(b); // line 32: error occurs here
  }
};

typedef classA<classB> usable;
int main (int argc, char* argv[]){
  int a = 5;
  usable::innerA<int>* myVar = usable::createInnerAs(a);

  return 0;
}

请帮助我,我已经面临这个问题好几天了。 这是不可能的,我想要做什么?还是我忘记了什么?

谢谢,Sema

【问题讨论】:

    标签: c++


    【解决方案1】:

    第 32 行应为:

    return A::template createInnerBs<innerA>(b);
    

    因为createInnerBs 依赖于模板参数A

    您还需要公开innerAinnerB 的构造函数。

    【讨论】:

    • 好的,谢谢,作为我的经验法则:当涉及模板时,始终使用 typename/template 在嵌套名称说明符中指定类型或模板。对吗?
    • 在 C++ 中它是 A::template smth 而不是 template A::smth 有什么合乎逻辑的原因吗?
    • @TigranSaluev:是的,您指定smth 是一个模板,因此关键字必须与之相关联。否则,您将无法指定更多嵌套模板,A::template B&lt;XXX&gt;::template C&lt;YYY&gt;::whatever
    【解决方案2】:

    这是为我编译的更正代码:

    class classB{ 
    public: 
      template < class iB> 
      class innerB{ 
        iB& ib; 
      public:
        innerB(iB& b) 
          :ib(b){} 
      }; 
    
      template<template <class> class classShell, class iB> 
      static classShell<iB>* createInnerBs(iB& b){ 
        // this function creates instances of innerB and its subclasses,  
        // because B holds a certain allocator 
    
        return new classShell<iB>(b); 
      }   
    }; 
    
    template<class A> 
    class classA{ 
      // intention of this class is meant to be a pluggable interface 
      // using templates for compile-time checking 
    public: 
      template <class iB> 
      class innerA: public A::template innerB<iB>{ 
      public:
        innerA(iB& b) 
          : A::template innerB<iB>(b){} 
      }; 
    
      template<class iB> 
      static inline innerA<iB>* createInnerAs(iB& b);
    }; 
    
    template<class A> 
    template<class iB> 
    inline classA<A>::innerA<iB>* classA<A>::createInnerAs(iB& b)
    { 
        return A::template createInnerBs<classA::template innerA>(b);
    } 
    
    typedef classA<classB> usable; 
    int main (int argc, char* argv[]){ 
      int a = 5; 
      usable::innerA<int>* myVar = usable::createInnerAs(a); 
    
      return 0; 
    } 
    

    即使我认为你把事情复杂化了......但我并不完全理解你的用例。

    【讨论】: