C++ 如何在派生类的Ctor中使用模板基类中的typedef?
如果我有一个基类和一个派生类,这两个模板都是:C++ 如何在派生类的Ctor中使用模板基类中的typedef?,c++,templates,inheritance,C++,Templates,Inheritance,如果我有一个基类和一个派生类,这两个模板都是: template <typename T> class Base { public: typedef T (*func)(); Base(func f):m_f(f){}; T invoke(){ return m_f();}; private: func m_f; }; template <typename D> class Derived : public Base<D> {
template <typename T>
class Base {
public:
typedef T (*func)();
Base(func f):m_f(f){};
T invoke(){ return m_f();};
private:
func m_f;
};
template <typename D>
class Derived : public Base<D> {
public:
Derived(Base<D>::func f) : Base<D>(f) { };
D foo() {
return Base<D>::invoke();
}
};
模板
阶级基础{
公众:
typedef T(*func)();
基(func f):m_f(f){};
T invoke(){return m_f();};
私人:
func m_f;
};
模板
派生类:公共基{
公众:
派生的(Base::func f):Base(f){};
D foo(){
返回Base::invoke();
}
};
派生类需要传递一个函数指针到Ctor中的基。阅读后,我了解到应按以下方式调用Ctor中的typedef:
Derived(Base<D>::func f) : Base<D>(f) {};
Derived(Base::func f):Base(f){};
但是,当我尝试编译时:
int returnZero(){
return 0;
}
Derived<int> d(returnZero);
std::cout << d.foo() << std::endl;
int returnZero(){
返回0;
}
导出d(返回零);
std::coutclangas通常会给出一条非常有用的错误消息,解释一切:
error: missing 'typename' prior to dependent type name 'Base<D>::func'
Derived(Base<D>::func f) : Base<D>(f) { };
^~~~~~~~~~~~~
typename
错误:在依赖类型名称“Base::func”之前缺少“typename”
派生的(Base::func f):Base(f){};
^~~~~~~~~~~~~
字体名
如果从属名称是类型或模板,则应分别使用typename
或template
关键字消除歧义
这是必需的,因为在派生的
定义中,编译器不知道将使用什么类型来代替D
,因此由于可能的专门化,它不知道Base
的实际定义是什么。这就是为什么Base
中的任何标识符都依赖于类型D
然而,编译器仍然需要能够解析它只能部分理解的代码,这就是为什么您需要帮助它,告诉它标识符func
不仅仅是Base
的成员,而是typename
,因为这定义了可以使用该标识符的上下文。
另一方面:对于只能使用类型的上下文,例如您的上下文,有一种方法可以消除这种恼人的规则。叮当声通常会给出一条非常有用的错误消息,解释一切:
error: missing 'typename' prior to dependent type name 'Base<D>::func'
Derived(Base<D>::func f) : Base<D>(f) { };
^~~~~~~~~~~~~
typename
错误:在依赖类型名称“Base::func”之前缺少“typename”
派生的(Base::func f):Base(f){};
^~~~~~~~~~~~~
字体名
如果从属名称是类型或模板,则应分别使用typename
或template
关键字消除歧义
这是必需的,因为在派生的
定义中,编译器不知道将使用什么类型来代替D
,因此由于可能的专门化,它不知道Base
的实际定义是什么。这就是为什么Base
中的任何标识符都依赖于类型D
然而,编译器仍然需要能够解析它只能部分理解的代码,这就是为什么您需要帮助它,告诉它标识符func
不仅仅是Base
的成员,而是typename
,因为这定义了可以使用该标识符的上下文。
另一方面:对于只能使用类型的上下文(例如您的上下文),有一个方法可以消除这个恼人的规则