c++ - 多个嵌套的相关名称 - 在哪里粘贴 typename 关键字?

标签 c++ templates typename dependent-name

这个问题的灵感来自 this other question .在尝试回答这个问题时,我明白我自己也有很多问题。所以...请考虑以下事项:

struct S1
{
    enum { value = 42 };
};

template <class T> struct S2
{
    typedef S1 Type;
};

template <class T> struct S3
{
    typedef S2<T> Type; 
};

template <class T> struct S4
{
    typedef typename T::Type::Type Type;  //(1)//legal?
    enum {value = T::Type::Type::value }; //(2)//legal?
};

int main()
{
    S4<S3<S2<S2<S1> > > >::value;
}

这可以通过 MSVC9.0 和 Online Comeau 成功编译。但是,困扰我的是我不明白 typename 在 (1) 中指的是什么以及为什么我们不需要 typename 在 ( 2).

我已经尝试了这两种我认为应该在 MSVC 上失败的语法(语法?):

    typedef typename T::typename Type::Type Type;
    enum {value = typename T::typename Type::Type::value }; 

    typedef typename (typename T::Type)::Type Type;
    enum {value = (typename (typename T::Type)::Type)::value }; 

当然,解决方法是像这样使用连续的 typedef:

   typedef typename T::Type T1;
   typedef typename T1::Type Type;
   enum { value = Type::value};  

抛开良好的风格,我们是否在句法上必须使用我提到的解决方法?

剩下的只是一个有趣的例子。无需阅读。与问题无关。

请注意,虽然 MSVC 接受没有多个 typename 的原始奇怪语法(我的意思是 (1) 和 (2)),但它会导致上述问题中的奇怪行为。我想我也会在这里以简洁的形式展示这个例子:

struct Good
{
    enum {value = 1}; 
};
struct Bad
{
    enum {value = -1};  
};

template <class T1, class T2>
struct ArraySize
{
    typedef Bad Type;
};
template <class T>
struct ArraySize<T, T>
{
    typedef Good Type;
};

template <class T>
struct Boom
{
    char arr[ArraySize<T, Good>::Type::value]; //error, negative subscript, even without any instantiation
};

int main()
{
    Boom<Good> b; //with or without this line, compilation fails.
}

这不会编译。我提到的解决方法解决了这个问题,但我确信这里的问题是我最初的问题——缺少类型名,但你真的不知道该把它贴在哪里。 非常感谢。

最佳答案

范围运算符:: 之前的名称必须始终是命名空间或类(或枚举)名称,并且命名空间名称不能依赖。所以你不必告诉编译器这是一个类名。


标准说([temp.res] 部分)不是我编造的:

A qualified name used as the name in a mem-initializer-id, a base-specifier, or an elaborated-type-specifier is implicitly assumed to name a type, without the use of the typename keyword. In a nested-name-specifier that immediately contains a nested-name-specifier that depends on a template parameter, the identifier or simple-template-id is implicitly assumed to name a type, without the use of the typename keyword. [ Note: The typename keyword is not permitted by the syntax of these constructs. — end note ]

T::T::Type::T::Type::Type::嵌套的-name-specifiers,它们不需要用typename标记。

本节显然可以并且可以说应该在豁免列表中包含 typedef 声明的类型说明符。但请记住,类型说明符 可能会变得非常复杂,尤其是在 typedef 声明中。现在很可能在 typedef type-specifier 中多次需要 typename 关键字,因此需要更多的分析才能让我相信 typename 在 typedef 中永远不是必需的。

typedef typename T::Type::Type 类型 中,T::Type::Type 需要使用 typename 关键字,因为它的 nested-name-specifier (T::Type::) 是一个从属名称,并且标准说(同一部分):

When a qualified-id is intended to refer to a type that is not a member of the current instantiation (14.6.2.1) and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword typename, forming a typename-specifier. If the qualified-id in a typename-specifier does not denote a type, the program is ill-formed.

关于c++ - 多个嵌套的相关名称 - 在哪里粘贴 typename 关键字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6642721/

相关文章:

C++ 如何创建一个将函数指针的引用作为参数的函数?

c++ - 超大矩阵的决定值

c++ - C++ 结构成员模板函数的显式特化——这是 Visual Studio 的问题吗?

c++ - 在模板中返回一个迭代器

c++ - 如何找到由 3 个点和 3 个红外 LED 组成的三角形的旋转和平移

c++ - 一个接口(interface)可以只指定方法名,而不指定返回类型吗?

constexpr 和返回模板函数的 C++0x 错误

c++ - 将 std::result_of<> 用于成员类型的成员方法

c++ - 为什么必须在哪里放置 “template”和 “typename”关键字?

C++:从结构中的静态函数中提取参数类型