当我写A::B::C
时,与 A
是一个类,并且 B
作为它的基类,我假设我正在访问 C
这是在该基 B
中定义的。当 B
时,这不起作用。实际上并不是 A
的基础。然而,当 B
时,显然情况并非如此。是一个模板,例如A::B<123>::C
仍然给我 B<123>::C
,并且 B<123>
似乎并不重要。实际上是 A
的基数或不。我不知道为什么会有差异。难道不解释A::B<123>
作为访问基类 B<123>
类A
?为什么不?是否可以以某种方式重写它,以便它像访问基类一样解释它?
这是一个片段,详细解释了所做的事情,并带有解释每个步骤的注释:
// Here we show that we can't access a non-existent base of A
namespace WorksAsExpectedWithoutTemplates {
struct B
{
using C = void;
};
struct D
{
using C = void;
};
struct A: B
{
};
// Compiles as expected, B is a base of A, so Foo is B::C, aka void
using Foo = A::B::C;
// Doesn't compile, as expected, because D isn't a base of A, even though D::C
// exists
using Bar = A::D::C; // WE DON'T EXPECT THIS TO COMPILE, WHICH IS FINE
}
// Now we try the same thing with templates, and it doesn't behave the same way.
// Why?
namespace ActsDifferentlyWithTemplates {
template< int >
struct B
{
using C = void;
};
struct A: B< 42 >
{
};
// Compiles as expected, B< 42 > is a base of A, so Foo is B< 42 >::C, aka void
using Foo = A::B< 42 >::C;
// Compiles, Bar is B< 123 >::C, even though B< 123 > is not a base of A. Why
// does this behave differently than in the non-template case above? Can this be
// rewritten differently so that this wouldn't compile, same as in
// WorksAsExpectedWithoutTemplates, since B< 123 > isn't a base of A?
using Bar = A::B< 123 >::C; // WHY DOES THIS COMPILE? B< 123 > isn't a base of A
}
最佳答案
template< int > struct B
有一个 injected-class-name B
如果它紧接在 <
之前,则充当模板名称。 。类(class)struct A
继承了这一点。
所以,A::B< 123 >::C
与 B< 123 >::C
相同,不是基类 B< 42 >
。例如:
template<int X>
struct B {
using C = char[X];
};
struct A : B<42> {};
using Foo = A::B<42>::C;
using Bar = A::B<123>::C;
using Baz = A::B::C; // (injected-class-name without template)
static_assert(sizeof(Foo) == 42);
static_assert(sizeof(Bar) == 123); // This is a different type
static_assert(sizeof(Baz) == 42);
这些情况实际上都不是“访问基类”。它们都像任何其他成员类型别名/成员模板一样从基类继承注入(inject)类名。
关于c++ - 当基类是模板时,访问基类时的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71866374/