这是我能提出的最小例子:
template <typename T>
struct Util
{
using Type = int;
};
struct A
{
struct B : public Util<B> {
void fun(Type) {}
};
};
template <typename T>
struct C
{
struct D : public Util<D> {
void fun(Type) {}
};
};
int main()
{
A::B{}.fun(0);
C<int>::D{}.fun(0);
}
A::B
和C::D
之间的唯一区别是C
是模板。
struct C::D
无法编译,并出现以下错误:
test_cpp.cpp:18:18: error: ‘Type’ has not been declared
void fun(Type) {}
^~~~
为什么这不能编译?我如何进行编译?
假设Util来自外部库并且我无法更改它(如果你有勇气的话,那就是boost::iterator_facade
。)
答案 0 :(得分:3)
此时:
template <typename T>
struct C
{
struct D : public Util<D> {
void fun(Type) {} // <-- here
};
};
编译器无法知道<{em> * * Type
需要来自Util<D>
的范围。调用基类成员函数也是同样的问题,需要使用this->
明确限定,否则无法找到它们。
您应该能够通过明确限定类型来解决此问题:
void fun(typename Util<D>::Type) {}
请参阅complete snippet on Coliru。
差异背后的原因是,正如@ etam1024在评论中正确指出的那样,在A::B
中,Type
是非依赖名称,而在C::D
中它是依赖名称。有关基类成员函数this answer的成员函数限定的类似情况的解释,请参阅。
*在我看来,编译器可以知道在哪里寻找Type
,但语言规则说它看起来并不那么远。注意我可能会忽略特殊情况,编译器无法推断出这种情况,因此导致需要完全koalafication的一般情况。