Почему SFINAE портится при изменении места специализации шаблона класса? Это ошибка C ++? - PullRequest
6 голосов
/ 06 марта 2012

Следующий код выдает ожидаемую ошибку компилятора ( Demo ):

  1 template<bool> struct Range;
  2 
  3 template<int value, typename = Range<true> > struct Unique;
  4 template<int value> struct Unique<value, Range<(value > 1)> > { typedef char type[1]; };
  5 template<int value> struct Unique<value, Range<(value > 2)> > { typedef char type[2]; };
  6 
  7 Unique<3>::type o1;
  8 Unique<3>::type o2;

Теперь, если я поменяю местами 5 и 7.Тогда НЕТ ошибки компилятора !! Демо .

  5 Unique<3>::type o1;

  7 template<int value> struct Unique<value, Range<(value > 2)> > { typedef char type[2]; };

Для o1 понятно, что ошибок нет, поскольку специализация для (value > 2) еще не видна.Но почему также нет ошибки для o2, который видит 2 совпадающие специализации!?
Я предполагаю, что компилятор должен выбрать Unique<3>::type с некоторым произвольным именем, когда он встречается в первый раз, а затем заменить Unique<3>::type везде с таким именем.

Это ошибка компиляции или ошибка C ++ или функция C ++ " * "?

Ответы [ 3 ]

3 голосов
/ 06 марта 2012

Шаблон создается в первый раз, когда он необходим (в модуле перевода), а не каждый раз.

2 голосов
/ 06 марта 2012

o1 не видит вторую специализацию из-за этого:

14.5.5 / 1 Частичная специализация должна быть объявлена ​​до первого использования классаспециализация шаблона, которая будет использовать частичную специализацию в результате неявного или явного создания экземпляра в каждой единице перевода, в которой происходит такое использование; диагностика не требуется .

Во втором примере вторая специализация будет использоваться в экземпляре Unique<3>, если она была замечена до объявления o1.Поскольку это правило нарушается, программа нарушается, и компилятору разрешается об этом молчать.

o2 не видит вторую специализацию, потому что вообще не видит никакой специализации.Его класс создается один раз, в точке объявления o1.

2 голосов
/ 06 марта 2012

В 14.5.5.1 Совпадение частичных специализаций шаблона класса , существует

Если найдено более одной совпадающей специализации, правила частичного порядка (14.5.5.2)используется для определения того, является ли одна из специализаций более специализированной, чем другие.Если ни одна из специализаций не является более специализированной, чем все другие соответствующие специализации, то использование шаблона класса является неоднозначным, и программа является неправильной.

Однако это относится только к вашейпервый случай, когда видны две специализации, и я пока не уверен, что эти две специализации действительны сами по себе.

Однако во втором случае до достижения второй специализации шаблон template-id Unique<3> уже существует, для которого (благодаря nm, Matthieu M., James Kanze) первая специализация уже создана:

14.5.5 Частичные специализации шаблона класса

Частичная специализация должна быть объявлена ​​до первого использования специализации шаблона класса, которая будет использовать частичную специализацию в результате неявной или явной реализации в каждой единице перевода, в которой происходит такое использование.;Диагностика не требуется.

И в 14.5.5, элемент 8

В списке аргументов частичной специализации шаблона класса, следующееприменяются следующие ограничения:

- Частично специализированное нетипичное выражение аргумента не должно включать параметр шаблона частичной специализации, кроме случаев, когда выражение аргумента является простым идентификатором.[> Пример:

template <int I, int J> struct A {};

template <int I> struct A<I+5, I*2> {}; // error

template <int I, int J> struct B {};

template <int I> struct B<I, I> {}; // OK

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

Таким образом, кажется, что нетипичные аргументы не участвуют в создании специализации, если не используются в качестве простого идентификатора (таким образом, Range<(value > 2)> будет неправильным).

Так что кажетсяВаш код неправильно сформирован.


Не имеет прямого отношения, но все же интересен в этом отношении:

14.7.3 Явная специализация

Размещение явных объявлений специализации для шаблонов функций, шаблонов классов, функций-членов шаблонов классов, статических данных-членов шаблонов классов, классов-членов шаблонов классов, шаблонов классов-членов шаблонов классов, функции-членашаблоны шаблонов классов, функции-члены шаблонов элементов шаблонов классов, функции-члены шаблонов-членов классов, не являющихся шаблонами, шаблоны функций-членов классов-членов шаблонов классов и т. д., а также местоПри объявлении частичной специализации шаблонов классов, шаблонов классов-членов классов, не являющихся шаблонами, шаблонов классов-членов шаблонов классов и т. д., может влиять на правильность формирования программы в соответствии с относительным позиционированием явные объявления специализации и точки их создания в модуле перевода, как указано выше и ниже. При написании специализации будьте осторожны с ее местоположением;или сделать его компиляцией будет таким испытанием, чтобы разжечь его самосожжение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...