Дан следующий шаблон класса:
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
что (правильно) будет неполный тип, если вы удалите его определения.