Clang++ ошибка типа автоматического возврата для специализации шаблонного метода в шаблонном классе?

Пытаясь понять другой вопрос, я упростил пример, получив следующий код.

template <bool>
struct foo
 {
   template <typename T>
      auto bar (int i)
       { return i; }
 };

template <>
template <typename T>
   auto foo<true>::bar (int i)
    { return i; }

int main()
 {
   return 0;
 }

g++ 4.9.2 компилирует без проблем; clang++ 3.5 выдает следующую ошибку

tmp_003-14,gcc,clang.cpp:12:20: error: out-of-line definition of 'bar' does not
      match any declaration in 'foo<true>'
   auto foo<true>::bar (int i)
                   ^~~

Заменив одно из двух возвращаемых значений auto на int, изменений нет: g++ compile и clang++ выдают ошибку. Заменив оба auto на int, ошибка исчезнет.

Часть template <typename T> важна, потому что следующий код без проблем компилируется обоими компиляторами.

template <bool>
struct foo
 {
      auto bar (int i)
       { return i; }
 };

template <>
   auto foo<true>::bar (int i)
    { return i; }

int main()
 {
   return 0;
 }

Мой вопрос очевиден: кто прав?

г++ или клан++?

Я предполагаю, что g++ прав и что это ошибка от clang++, но я прошу подтверждения.

p.s.: извините за мой плохой английский.


person max66    schedule 27.06.2016    source источник
comment
Попробуйте gcc 6.1 и clang 3.8..   -  person Jesper Juhl    schedule 27.06.2016
comment
Это была проблема Clang. Он работает с 3.8: godbolt.org/g/JkCJ6l   -  person kirbyfan64sos    schedule 27.06.2016


Ответы (1)


У меня была такая же проблема, вот решение. Кроме того, вы также должны учитывать, что неявный тип автоматического возврата разрешен только с C++ 14, поэтому вы должны либо использовать флаг компиляции -std=c++14, либо явно указать тип возврата (для C++ 11).

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

template <bool>
struct foo;

template <>
struct foo <false>
{
   template <typename T>
   auto bar (int i)
   { return i; }
};


template <>
struct foo <true>
{
   template <typename T>
   auto bar (int i)
   { return i; }
};

int main()
{
   return 0;
}
person luart    schedule 16.07.2016
comment
Спасибо за ваши усилия, но ваша ссылка на решение - это та же ссылка на другой вопрос, который я цитирую в своем вопросе. И принятое решение — это мой ответ на этот вопрос. И, очевидно, где речь идет о C++14, не о C++11, о том, как он помечен (тега C++11 нет). Мой вопрос не в том, как решить? но кто прав?. Вы говорите (если я правильно понимаю), что g++ правильный, а clang++ неправильный. Но я надеялся на ответ, в котором будет указана соответствующая часть официального стандарта. (извините еще раз за мой плохой английский). - person max66; 16.07.2016
comment
Привет, @max66, прости, что не узнал тебя сразу, ты был первым, кто предложил решение. Для меня нет вопроса, кто прав: стандарт допускает объявление шаблона, которое также является определением, и допускает специализацию шаблонов. Таким образом, очевидно, что в CLang просто не хватает определения функции шаблона специализации класса шаблона в случае, когда объявление класса шаблона также является его определением. Это не ошибка CLand, просто еще не реализованная функция, потому что CLang молодой и CLang 3.8.1 совместим с GCC 4.2.1 (это довольно старая версия). - person luart; 17.07.2016