2013-07-16 24 views
19

Otrzymuję błędy kompilacji podczas próby wywołania konstruktora klasy podstawowej w wyprowadzonej liście inicjalizacyjnej, gdy używany jest szablon szablonu z parametrem CRTP.clang ++ nie akceptuje użycia parametru szablonu przy korzystaniu z CRTP

Problem mogą być replikowane z tym fragmencie kodu:

template <template<class> class Derived, class T> 
struct base 
{ 
}; 

template <class T> 
struct derived : public base<derived, T> 
{ 
    derived() 
     : base<derived, T>() 
    { } 
}; 

messsage błąd popełniła:

bug.cpp:10:16: error: template argument for template template parameter must be a class template or type alias template 
     : base<derived, T>() 
      ^
bug.cpp:10:11: error: expected class member or base class name 
     : base<derived, T>() 
     ^
bug.cpp:10:11: error: expected '{' or ',' 
3 errors generated. 

Ten problem pojawia się tylko zdarzyć się na brzękiem (3.4) nie g ++ (4,8, 4,7, 4,6). Kompiluję także z opcją -std = C++ 11.

Po raz pierwszy potrzebowałem programu CRTP z parametrem szablonu szablonu. Czy robię to dobrze i jest to problem z clang ++, czy nie?

Urosłem zaufać komunikatom o błędach +++ +++ niż g ++ późno!

Odpowiedz

17

Twój kod jest legalny.

Z C++ 11 Standard, rozdział 14.6.1:

jak normalnych (nie-szablonu) klas, szablony klasy mają wstrzykuje-Class-name (klauzula 9). Nazwa klasy wtryskiwanej może być użyta jako nazwa szablonu lub nazwa typu. Gdy jest używany z listą szablonów argumentów, jako szablon-argument dla szablonu szablonu-parametru, lub jako ostateczny identyfikator w specyfikacji określonego typu deklaracji szablonu klasy przyjaciela, do samego szablonu klasy.

Wygląda na to, że Twoja wersja clang nadal implementuje starą regułę. W oparciu o dodatkowe komentarze, może to być robione tylko na liście inicjatora ctor .


użytkownika David Rodríguez - dribeas warunkiem obejście dla kompilatorów, które nie zostały w pełni wdrożone w C++ 11 wstrzykuje-nazwa-klasy regułę. Użyć dowolnej nazwy klasy, która nie jest bez zastrzeżeń, na przykład:

derived() 
    : base< ::derived, T >() 
//   ^^ qualified with global namespace 
{ } 

Niektóre kompilatory mogą wymagać to na liście spadkowego także:

template <class T> 
struct derived : public base< ::derived, T > 
//       ^^ 
+0

+1 nie wiedział, że to się nie zmieniło w C++ 11. Możesz podać obejście, które miałem w usuniętej odpowiedzi. –

+0

@ DavidRodríguez-dribeas: nie martw się, nowy standard wciąż mnie często zaskakuje. –

+1

Nie martwię się, wręcz przeciwnie, nauczyłem się czegoś. Byłbym zmartwiony dniem, w którym niczego się nie nauczyłem :) –

Powiązane problemy