Дан следующий шаблон класса:
template<typename T>
struct Outer
{
struct Inner;
auto f(Inner) -> void;
};
мы определяем Innerотдельно для каждой специализации Outer:
template<>
struct Outer<int>::Inner {};
template<>
struct Outer<double>::Inner {};
а затем определить функцию-член fодин раз для всех специализаций Outer:
auto Outer<T>::f(Inner) -> void
{
}
но Кланг (9.0.0) жалуется:
error: variable has incomplete type 'Outer::Inner'
auto Outer<T>::f(Inner) -> void
^
Мы можем избежать ошибки компилятора, также предоставив определение Innerдля всех других специализаций Outer:
template<typename T>
struct Outer<T>::Inner {};
или определяя fотдельно для каждой специализации:
template<>
auto Outer<int>::f(Inner) -> void
{
}
template<>
auto Outer<double>::f(Inner) -> void
{
}
И GCC, и MSVC принимают исходный код, который вызывает вопрос; это ошибка Clang или единственная совместимая реализация из трех?
Innerдля всех других специализаций, и определение fотдельно для каждой специализации устраняет ошибку компиляции.
Innerон представляется как неполный тип, несмотря на определения для каждой специализации Outer. Ясно, Innerчто (правильно) будет неполный тип, если вы удалите его определения.