简答:每当引用作为从属名称的嵌套名称时,即嵌套在具有未知参数的模板实例中。
长答案:C++ 中有三层实体:值、类型和模板。所有这些都可以有名称,仅名称并不能告诉您它是哪一层实体。相反,必须从上下文中推断出有关名称实体性质的信息。
当这种推论不可能时,你必须指定它:
template <typename> struct Magic; // defined somewhere else
template <typename T> struct A
{
static const int value = Magic<T>::gnarl; // assumed "value"
typedef typename Magic<T>::brugh my_type; // decreed "type"
// ^^^^^^^^
void foo() {
Magic<T>::template kwpq<T>(1, 'a', .5); // decreed "template"
// ^^^^^^^^
}
};
这里的名称Magic<T>::gnarl、Magic<T>::brugh 和Magic<T>::kwpq 必须明确说明,因为无法分辨:由于Magic 是一个模板,该类型的性质 Magic<T> 依赖于 T -- 例如,可能存在与主模板完全不同的特化。
使Magic<T>::gnarl 成为依赖名称的原因是我们位于模板定义中,而T 是未知的。如果我们使用Magic<int>,情况会有所不同,因为编译器知道(你保证!)Magic<int> 的完整定义。
(如果你想自己测试,这里有一个 Magic 的示例定义,你可以使用。为了简洁,请原谅在专业化中使用 constexpr;如果你有一个旧的编译器,请随意更改静态成员常量声明为旧式 C++11 之前的形式。)
template <typename T> struct Magic
{
static const T gnarl;
typedef T & brugh;
template <typename S> static void kwpq(int, char, double) { T x; }
};
template <> struct Magic<signed char>
{
// note that `gnarl` is absent
static constexpr long double brugh = 0.25; // `brugh` is now a value
template <typename S> static int kwpq(int a, int b) { return a + b; }
};
用法:
int main()
{
A<int> a;
a.foo();
return Magic<signed char>::kwpq<float>(2, 3); // no disambiguation here!
}