В общем так.
Код без шаблона не собирается потому как не корректный:
struct AA
{
using X = void();
X x;
};
//AA::X AA::x{}; // Так нельзяvoid AA::x() { } // Нет проблем
С шаблонами выходит всё веселее:
struct A
{
template<class T>
using X = void();
template<class T>
X<T> x;
};
template<class T>
A::X<T> A::x{};
Компилируется в GCC и VC
Clang:
error: out-of-line declaration of a member must be a definition [-Wout-of-line-declaration]
!!error: illegal initializer (only variables can be initialized)
Хочу заметить, что VC позволяет писать без ';' в конце т.е. A::X<T> A::x{};
А далее разные компиляторы дают разный результат.
void TestA()
{
A a;
a.x<int>();
}
VC: Всё собирается и работает.
GCC: undefined reference to `void A::x<int>()'
Здравствуйте, _NN_, Вы писали:
_NN>Как обычно вопрос кто здесь прав ?
Шланг, ессно. VC не может быть прав по определению, следовательно и gcc тоже на кривую дорожку вылез.
</s>
Здравствуйте, yatagarasu, Вы писали:
Y>Здравствуйте, _NN_, Вы писали:
_NN>> using X = void(); _NN>>AA::X AA::x{};
Y>Объясните что тут вообще происходит?
— либо определение метода AA::x, возвращающего указатель на функцию void() — но в AA нет такого метода, так-что
— инициализация члена AA:x, являющегося указателем на функцию void() (но список инициализации пуст, потому шланг и ругается)
_NN>>> using X = void(); _NN>>>AA::X AA::x{};
Y>>Объясните что тут вообще происходит? D>- либо определение метода AA::x, возвращающего указатель на функцию void() — но в AA нет такого метода, так-что D>- инициализация члена AA:x, являющегося указателем на функцию void() (но список инициализации пуст, потому шланг и ругается)
Почему это указатель на функцию ?
X = void() .
X x = void x();
struct A { using X = void(); X x; }
void A::x() {}
Здравствуйте, _NN_, Вы писали:
_NN>>>> using X = void(); _NN>Тут нет никакого указателя.
А, ну да, тогда наврал. Мне почему-то всегда казалось что разницы между функцией и указателем на функцию в объявлениях нет.
Здравствуйте, _NN_, Вы писали: _NN>С шаблонами выходит всё веселее: _NN>
_NN>struct A
_NN>{
_NN> template<class T>
_NN> using X = void();
_NN> template<class T>
_NN> X<T> x;
_NN>};
_NN>template<class T>
_NN>A::X<T> A::x{};
_NN>
_NN>Компилируется в GCC и VC _NN>Clang:
error: out-of-line declaration of a member must be a definition [-Wout-of-line-declaration]
_NN>!!error: illegal initializer (only variables can be initialized)
_NN>
_NN>Как обычно вопрос кто здесь прав ?
В стандарты не лазил, но исходя из здравого смысла, конструкция
_NN>template<class T>
_NN>A::X<T> A::x{};
— это ведь не определение метода.
Определение метода было бы вот:
Здравствуйте, _NN_, Вы писали:
_NN>Здравствуйте, wander, Вы писали:
W>>Как это на осилил!!? _NN>Я тестировал на ideone.com: https://ideone.com/i3JFpY
Посмотрел на его ошибки:
prog.cpp:25:32: error: 'type' in 'struct return_type<A::X<T> >' does not name a type
typename return_type<A::X<T>>::type A::x()
^
prog.cpp:25:37: error: prototype for 'int A::x()' does not match any in class 'A'
typename return_type<A::X<T>>::type A::x()
^
prog.cpp:21:10: error: candidate is: template<class T> void A::x()
X<T> x;
Что-то у меня большое подозрение, что он лажает.
A::X<T> — это void(), void() — это тип функции. Шаблон return_type выделяет тип void из типа void().
А тут, он получается не смог это сделать. Хотя, если посмотреть какой тип имеет X<T>, то явно показывает, что void(). Непонятно!
_NN>Спасибо за еще один ресурс онлайн компилятора.