GCC / CLang не согласны с частичной специализацией параметра шаблона - PullRequest
0 голосов
/ 09 октября 2018

GCC и clang не согласны с этим кодом.

#include <type_traits>

template <typename T, template <typename...> typename Tpl> 
struct storage {
    using type_t = T;

    template <typename... Args>
    using storage_tpl = Tpl<Args...>;
};

template <typename T, template <typename...> typename>
struct F{
    constexpr static int x = 1;
};

template <typename T >
struct F<T, std::void_t>{
    constexpr static int x = 2;
};

int f() {
    using S = storage<int, std::void_t>;

    static_assert(F<int, S::storage_tpl>().x == 2);

    return F<int, S::storage_tpl>().x;
}

Согласно clang S::storage_tpl не является std::void_t;следовательно, он выбирает основной шаблон F вместо частичной специализации и, следовательно, утверждения.

На первый взгляд, похоже, что GCC прав, потому что понимает, что вложенный шаблон является просто псевдонимом для std::void_t, номожет быть, он слишком умный, и стандарт требует, чтобы S::storage_tpl и std::void_t были двумя разными шаблонами.

Кто прав?

1 Ответ

0 голосов
/ 10 октября 2018

Похоже, что это не определено в данный момент и ч / т для TC похоже, что это покрыто Отчет о дефектах CWG 1286 , который гласит:

Проблема 1244 была решена путем изменения примера в 17.5 [temp.type] параграфа 1 с

 template<template<class> class TT> struct X { };
  template<class> struct Y { };
  template<class T> using Z = Y<T>;
  X<Y> y;
  X<Z> z;

на

  template<class T> struct X { };
  template<class> struct Y { };
  template<class T> using Z = Y<T>;
  X<Y<int> > y;
  X<Z<int> > z;

Фактически первоначальная цель заключалась в том, чтобы примердолжно быть правильно, как написано;Тем не менее, нормативная формулировка, чтобы сделать это так отсутствовал.Нынешняя формулировка 17.6.7 [temp.alias] имеет дело только с эквивалентностью специализации шаблона псевдонима с идентификатором типа после замены.Необходимо добавить формулировку, указав, при каких обстоятельствах сам шаблон псевдонима эквивалентен шаблону класса.

и предлагает следующее решение:

Добавить следующее как новыйабзац после 17.6.7 [temp.alias] абзац 2:

Когда идентификатор типа в объявлении шаблона псевдонима (назовите его A) состоит из простого идентификатора шаблона, в котором аргумент шаблонасписок состоит из списка идентификаторов, каждый раз именующих каждый шаблон-параметр A ровно в том же порядке, в котором они появляются в списке template-parameter A, шаблон псевдонима эквивалентен шаблону, названному в simple-template-id (callэто T) если A и T имеют одинаковое количество шаблонов-параметров.[Сноска: Это правило является транзитивным: если шаблон псевдонима A эквивалентен другому шаблону псевдонима B, эквивалентному шаблону класса C, то A также эквивалентен C, а A и B также эквивалентны друг другу.- конец сноски] [Пример:

  template<typename T, U = T> struct A;

  template<typename V, typename W>
    using B = A<V, W>;                // equivalent to A

  template<typename V, typename W>
    using C = A<V>;                   // not equivalent to A:
                                      // not all parameters used

  template<typename V>
    using D = A<V>;                   // not equivalent to A:
                                      // different number of parameters

  template<typename V, typename W>
    using E = A<W, V>;                // not equivalent to A:
                                      // template-arguments in wrong order

  template<typename V, typename W = int>
    using F = A<V, W>;                // equivalent to A:
                                      // default arguments not considered

  template<typename V, typename W>
    using G = A<V, W>;                // equivalent to A and B

  template<typename V, typename W>
    using H = E<V, W>;                // equivalent to E

  template<typename V, typename W>
    using I = A<V, typename W::type>; // not equivalent to A:
                                      // argument not identifier

- конец примера]

, но есть проблемы с этим разрешением, и отчет о дефектах все еще активен.

...