使用 CRTP 时的可见性问题
Visibility problems when using CRTP
这是我能想出的一个最小示例:
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
是一个模板。
结构 C::D
编译失败,出现以下错误:
test_cpp.cpp:18:18: error: ‘Type’ has not been declared
void fun(Type) {}
^~~~
为什么编译失败?我该如何编译?
假设 Util 来自外部库,我无法更改它(如果你有兴趣,它是 boost::iterator_facade
)。
此时:
template <typename T>
struct C
{
struct D : public Util<D> {
void fun(Type) {} // <-- here
};
};
编译器无法知道 * Type
需要来自Util<D>
的范围。这与调用基 class 成员函数的问题相同,需要用 this->
明确限定,否则将找不到它们。
您应该能够通过显式限定类型来解决此问题:
void fun(typename Util<D>::Type) {}
差异背后的原因是,正如@etam1024 在评论中正确指出的那样,在 A::B
中,Type
是一个非依赖名称,而在 C::D
中它是从属名称。有关基本 class 成员函数 this answer.
的成员函数限定的类似情况的解释,请参见
* 在我看来,编译器 可以 知道在哪里寻找 Type
,但是语言规则说它不会找那么远。请注意,我可能忽略了编译器无法推断出这一点的特殊情况,因此导致需要完全 koalafication 的一般情况。
这是我能想出的一个最小示例:
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
是一个模板。
结构 C::D
编译失败,出现以下错误:
test_cpp.cpp:18:18: error: ‘Type’ has not been declared
void fun(Type) {}
^~~~
为什么编译失败?我该如何编译?
假设 Util 来自外部库,我无法更改它(如果你有兴趣,它是 boost::iterator_facade
)。
此时:
template <typename T>
struct C
{
struct D : public Util<D> {
void fun(Type) {} // <-- here
};
};
编译器无法知道 * Type
需要来自Util<D>
的范围。这与调用基 class 成员函数的问题相同,需要用 this->
明确限定,否则将找不到它们。
您应该能够通过显式限定类型来解决此问题:
void fun(typename Util<D>::Type) {}
差异背后的原因是,正如@etam1024 在评论中正确指出的那样,在 A::B
中,Type
是一个非依赖名称,而在 C::D
中它是从属名称。有关基本 class 成员函数 this answer.
* 在我看来,编译器 可以 知道在哪里寻找 Type
,但是语言规则说它不会找那么远。请注意,我可能忽略了编译器无法推断出这一点的特殊情况,因此导致需要完全 koalafication 的一般情况。