Моя проблема может быть возобновлена следующим фрагментом кода:
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 ++, только для того же кода, компилируется нормально!
Мои вопросы:
заранее спасибо
Leandro
Я думаю, что 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() {}
};
Значит, ссылка 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.