类模板,在定义中引用其自身的类型

时间:2018-06-26 00:18:21

标签: c++ templates language-lawyer metaprogramming

我想知道Visual Studio 2017和GCC中哪一个在关于标准的以下情况下是正确的。问题在于,在第二个类模板中,Visual Studio中的标识符“ second”始终引用具体类型,但是在gcc中,它似乎是上下文相关的。

GCC示例

template <typename...>
struct type_list{};

template<template <typename...> typename tmpl> 
struct tmpl_c
{
    template <typename...Ts> using type = tmpl<Ts...>;
};

template<typename> struct template_of;
template <template <typename...> typename tmpl, typename... Ts>
struct template_of<tmpl<Ts...>>{
    using type = tmpl_c<tmpl>; 

};


template <typename T>
struct first{};


template <typename T>
struct second
{
    // 'second' here refers to second<int>
    using test = second; 

    // 'second' here refers to the template second
    // is this due to the context? ie that the tmpl_c is expecting a template not a concrete type?
    using types = type_list<tmpl_c<first>, tmpl_c<second> >; 


    // second here refers to the concrete type 'second<int>'
    // this workaround is needed for visual studio as it seems second always 
    // refers to the concrete type, not the template.
    using types2 = type_list<tmpl_c<first>, typename template_of<second>::type >; 
};

Demo

还有Visual Studio示例(仅不同的位)

template <typename T>
struct second
{
    // 'second' here refers to second<int>
    using test = second; 

    // 'second' here refers to second<int>
    // this doesn't compile in visual studio as second<int> not the template.
    //using types = type_list<tmpl_c<first>, tmpl_c<second> >; 


    // second here refers to the concrete type 'second<int>'
    // this workaround is needed for visual studio as it seems second always 
    // refers to the concrete type, not the template.
    using types2 = type_list<tmpl_c<first>, typename template_of<second>::type >; 
};

Demo

由于template_of的两种解决方法均能正常工作,因此,这是我目前唯一的选择。.但我仍然想知道哪种方法正确,或者是否还有其他解决方法。

fixed in visual studio 15.8 Preview 2

1 个答案:

答案 0 :(得分:2)

Gcc是正确的。根据{{​​3}}的使用规则,注入的类名称还可以用作模板名称或类型名称。

(重点是我的)

  

与其他类一样,类模板具有注入的类名。注入的类名称可以用作模板名称或类型名称。

     

在以下情况下,injected-class-name被视为类模板本身的模板名称:

     
      
  • 后跟<< / li>   
  • 它用作与模板模板参数相对应的模板参数
  •   
  • 它是朋友类模板声明的详细类说明符中的最终标识符。
  •   
     

否则,它被视为类型名称,并且等效于模板名称,后跟<>中包含的类模板的模板参数。

那是

template <typename T>
struct second
{

    // second is same as second<T>
    using test = second; 

    // second is considered as a template-name
    // it's used as template argument for a template template parameter
    using types = type_list<tmpl_c<first>, tmpl_c<second> >; 

    // second is same as second<T>
    using types2 = type_list<tmpl_c<first>, typename template_of<second>::type >; 
};