метод шаблона и аргумент шаблона по умолчанию

Моя проблема может быть возобновлена ​​следующим фрагментом кода:

template <typename T> struct C2;

template <typename T>
struct C1
{
template <typename Type,
template <typename Ti> class Container = C2>
void m() {}
};template <typename T>
struct C2
{
template <typename Type = int,
template <typename Ti> class Container = C2> // <-- Here is the problem!
void m() {}

};

Компилятор gnu версии 4.8.1 завершает работу со следующим сообщением:

test-temp.C:16:47: error: invalid use of type ‘C2<T>’ as a default value for a template template-parameter
template <typename Ti> class Container = C2>

Это относится к параметру шаблона C2 по умолчанию для метода C2 :: m.

Видимо (это мое мнение), компилятор видит C2<T> в качестве параметра по умолчанию вместо C2 (без <T>). Таким образом, когда он находит инструкцию, он терпит неудачу, потому что тип C2<T> не совпадает с Container,

Тем не менее, Clang ++, только для того же кода, компилируется нормально!

Мои вопросы:

  1. Какой компилятор имеет правду?
  2. Есть ли альтернатива для выражения того же смысла с текущей версией компилятора gnu?

заранее спасибо

Leandro

9

Решение

Я думаю, что Clang верен, а g ++ ошибочен, цитирую черновик стандарта (жирный шрифт — мой)

14.6.1 Локально объявленные имена [temp.local]

1 Как и обычные (не шаблонные) классы, шаблоны классов имеют
имя введенного класса (пункт 9). Injectedclass-name может использоваться как
имя шаблона или имя типа. Когда он используется с
Шаблон-аргумент-список, как шаблон-аргумент для шаблона
Шаблон-параметр
, или как окончательный идентификатор в
подробный спецификатор объявления шаблона класса друга, он
ссылается на сам шаблон класса. В противном случае это эквивалентно
имя шаблона, за которым следуют параметры шаблона класса
шаблон заключен в <>.

Вы можете использовать :: оператор разрешения области действия, чтобы превзойти g ++ в представлении

template <typename T>
struct C2
{
template <typename Type = int,
template <typename Ti> class Container = ::C2>
// ^^ <-- here is the solution!
void m() {}

};

Живой пример.

9

Другие решения

Значит, ссылка 14.6.1 в ответе TemplateRex означает, что G ++ правильный (а Clang и VC ++ неправильные), чтобы принять это, поскольку он использует X в качестве аргумента шаблона для параметра шаблона шаблона?

template< template< typename > class T >
class factory { };

template< typename T >
class X
{
friend class factory< X >;  // ***
};

int main()
{
}

В этом примере G ++ рассматривает X как имя шаблона класса, тогда как Clang и VC ++ рассматривают его как имя внедренного класса.

Изменить: Clang 5.0.0 теперь принимает код, так же, как G ++ и EDG.

0

По вопросам рекламы [email protected]