шаблон класса, ссылающийся на свой собственный тип в определении - PullRequest
0 голосов
/ 26 июня 2018

Мне интересно, какая из visual studio 2017 и GCC верна в следующей ситуации со стандартом.Проблема заключается в том, что в секунде шаблона класса идентификатор 'second' в visual studio всегда ссылается на конкретный тип, но в 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 >; 
};

Демо

И пример 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 >; 
};

Демо

As* Обходной путь template_of, кажется, работает правильно в обоих случаях, в настоящее время это мой единственный вариант ... но я все еще хотел бы знать, какой из них правильный, или если есть другой обходной путь ..

исправлен в визуальномstudio 15.8 Preview 2

1 Ответ

0 голосов
/ 26 июня 2018

Gcc правильно.В соответствии с правилом использования injected-class-name для шаблона класса , 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 >; 
};
...