Извините за сложность названия этого вопроса; Я попытался описать минимальный SSCCE I, построенный для этой проблемы.
У меня есть следующий код:
#include <iostream>
namespace fizz
{
template<typename... Ts>
class bar
{
public:
template<int I, typename... Us>
friend auto foo(const bar<Us...> &);
private:
int i = 123;
};
template<int I, typename... Ts>
auto foo(const bar<Ts...> & b)
{
return b.i;
}
}
int main()
{
std::cout << fizz::foo<1>(fizz::bar<int, float>{});
}
Этот код компилируется с GCC 5.2 и не с Clang 3.7:
main.cpp:19:18: error: 'i' is a private member of 'fizz::bar<int, float>'
return b.i;
^
main.cpp:25:24: note: in instantiation of function template specialization 'fizz::foo<1, int, float>' requested here
std::cout << fizz::foo<1>(fizz::bar<int, float>{});
^
main.cpp:13:13: note: declared private here
int i = 123;
^
Однако, если вы немного измените код (хотя это не совсем полезно для меня, поскольку в реальном коде это приведет к появлению тонны шаблона):
#include <iostream>
namespace fizz
{
template<typename... Ts>
class bar
{
public:
template<int I, typename... Us>
friend int foo(const bar<Us...> &);
private:
int i = 123;
};
template<int I, typename... Ts>
int foo(const bar<Ts...> & b)
{
return b.i;
}
}
int main()
{
std::cout << fizz::foo<1>(fizz::bar<int, float>{});
}
он внезапно работает с этим Clang 3.7.
Разница в том, что в версии кода, который не компилируется с помощью Clang, шаблон функции friend использует С++ 14 auto
return type deduction, в то время как рабочий говорит, что возвращает int
. Такая же проблема возникает и с другими вариантами вывода типа auto
типа типа auto &&
или const auto &
.
Какой компилятор прав? Пожалуйста, предоставьте некоторые стандартные кавычки для поддержки ответа, так как вполне возможно, что ошибка должна быть подана для одного (... надеюсь, не обоих) компиляторов... или стандартного дефекта, если оба они правы (что бы не было " t в первый раз).