Zmarnowałem niezliczoną ilość godzin, aby zidentyfikować problem z gcc. Chciałem przetestować naszą bazę kodu za pomocą innego kompilatora, aby znaleźć więcej ostrzeżeń, które mogły zostać utracone przez Clang. Byłem zszokowany, że praktycznie połowa projektu przestała się kompilować z powodu niepowodzenia odrzucenia szablonu. Tutaj starałem się oswoić moją sprawę z najprostszym kodem.Wszystkie wersje GCC walczą z szablonem, który ma domyślny typ w definicji
#include <type_traits>
struct Foo
{ };
// This is a template function declaration, where second template argument declared without a default
template <typename T, typename>
void foo(const Foo & foo, T t);
// This is a template function definition; second template argument now has a default declared
template <typename T, typename = typename std::enable_if<1>::type>
void foo(const Foo & foo, T t)
{
}
int main(int argc, char ** argv)
{
foo(Foo{}, 1);
return 0;
}
ignorować 1
w std::enable_if<1>
. Oczywiście jest to stała wartość tylko po to, aby nie komplikować rzeczy, kiedy to nie ma znaczenia.
Ten fragment kodu zestawia [1] z szczęk (3,4 za pomocą 4,0) ICC (16, 17), Visual C++ (19.00.23506). Zasadniczo nie mogłem znaleźć żadnego innego kompilatora C++ 11, który, z wyjątkiem gcc (4.8 do 7.1), nie kompiluje tego fragmentu kodu.
Pytanie brzmi, kto ma rację, a kto się myli? Czy gcc zachowuje się zgodnie ze standardem?
Oczywiście nie jest to krytyczny problem. Mogę łatwo przenieść std::enable_if
do deklaracji. Jedyną ofiarą byłaby estetyka. Ale miło jest móc ukryć brzydki 100-literowy kod, który nie jest natychmiastowy dla użytkownika funkcji bibliotecznej w implementacji.
Przykład na żywo pod numerem godbolt.org.
Na stronie en.cppreference.com mówi o [domyślne argumenty szablonu] (http://en.cppreference.com/w/cpp/language/template_parameters#Default_template_arguments) »Domyślne argumenty szablonu, które pojawiają się w deklaracjach i definicji są połączone podobnie jak domyślne argumenty funkcji «. Dla [domyślne argumenty funkcji] (http://en.cppreference.com/w/cpp/language/default_arguments) znalazłem »... wskazane przez użycie następującej składni dla parametru na liście parametrów deklaracji funkcji« . Jeśli poprawnie to zinterpretuję, to * masz *, aby mieć domyślny argument w deklaracji. –
@HenriMenke, działa dla funkcji w ** gcc **: https://godbolt.org/g/kXNbYi. Wydaje się, że ** gcc ** ma podwójne standardy dla funkcji i szablonów ... – GreenScape
@HenriMenke Zobacz przykład "szablonu <...> klasa A" na 14.1/10. Działa tak jak w g ++, ale nie w przypadku zastąpienia klasy przez funkcję. –