如果我有两个模板的基类和派生类:
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();
}
};
派生类需要将函数指针传递给 Ctor 中的基址。阅读Inheritance and templates in C++ - why are methods invisible?后,我了解到Ctor中的typedef应该以以下方式调用:
Derived(Base<D>::func f) : Base<D>(f) {};
但是,当我尝试编译时:
int returnZero(){
return 0;
}
Derived<int> d(returnZero);
std::cout << d.foo() << std::endl;
我得到:
error: expected ')' before 'f'
Derived(Base<D>::func f) : Base<D>(f) { };
^
cpp_code.cpp: In function 'int main()':
cpp_code.cpp:59:27: error: no matching function for call to 'Derived<int>::Derived(int (&)())'
Derived<int> d(returnZero);
^
cpp_code.cpp:47:7: note: candidate: constexpr Derived<int>::Derived(const Derived<int>&)
class Derived : public Base<D> {
^~~~~~~
cpp_code.cpp:47:7: note: no known conversion for argument 1 from 'int()' to 'const Derived<int>&'
cpp_code.cpp:47:7: note: candidate: constexpr Derived<int>::Derived(Derived<int>&&)
cpp_code.cpp:47:7: note: no known conversion for argument 1 from 'int()' to 'Derived<int>&&'
在Ctor中使用函数指针(func)的正确方法是什么?
答案 0 :(得分:3)
通常,Clang会给出一条非常有用的错误消息,解释所有内容:
error: missing 'typename' prior to dependent type name 'Base<D>::func'
Derived(Base<D>::func f) : Base<D>(f) { };
^~~~~~~~~~~~~
typename
如果从属名称是类型或模板,则应分别使用typename
或template
关键字来消除歧义。
这是必需的,因为在Derived
定义中,编译器不知道将使用哪种类型来代替D
,因此它不知道{{1 }}由于可能的专业化。这就是Base<D>
内的任何标识符都依赖于类型Base<D>
的的原因。
但是,编译器仍然需要能够解析它只能部分理解的代码,这就是为什么您需要通过告诉标识符D
不只是{{1}的成员来提供帮助的原因},但func
,因为它定义了可以使用此标识符的上下文。