【发布时间】:2015-09-06 09:17:37
【问题描述】:
我正在尝试制作一个通用代码,如果 B 不是 D 的祖先,则会导致编译错误。我想出了什么:
template<typename B, typename D>
struct assert_base_of {
enum {value = sizeof(B::D)};
}
它不起作用。当我这样“称呼”它时:
assert_base_of<A2,A1>::value;
我收到以下错误(g++ 4.8.2):
main.cpp:16:22: error: ‘D’ is not a member of ‘A2’
看起来模板参数 D 没有被 A1 替换。谁能解释一下并提出解决方案?
【问题讨论】:
-
static_assert (std::is_base_of<B, D>::value, "B must be a base of D")有什么问题? -
我不允许使用 std::is_base_of,即使可以,我仍然想知道为什么 D 没有被替换 :)
-
B::D被解释为成员(不是类型),因为B在这里是依赖的。无论如何,你不能得到这样的基类——你需要将一个指针从D转换为B以检查D是否继承B。有关如何实施is_base_of,请参阅@Veritas 答案。 -
Bdependent 表示它依赖于一个模板参数(这里它是一个模板参数)。当您编写B::foo时,如果B是依赖的,则foo始终被解释为B成员的名称(这是因为编译器在您的模板上查看了两次,并且在第一遍中它不知道B最终会是什么)。如果你想让foo命名一个类型,你必须使用typename B::foo。如果要foo命名模板,则必须使用template B::foo。 -
另外,您在非模板
sizeof(A::B)案例中观察到的是将B的注入类名注入B(typenameB被“注入”到B,而A继承了它——A::A也作为一种类型存在)。这是您应该避免的 C++ 的一个黑暗角落,因为它与模板的行为不同。请参阅stackoverflow.com/questions/7025054/… 和相关问题。这里重要的是A::B命名一个类型,而不是一个成员。
标签: c++ templates scope-resolution