Инициализация (статических) переменных при конкретизации шаблона

Объявлены следующие классы

template <typename T>
class Z
{
    static constexpr std::size_t N{0};

    static constexpr std::array<int, N> v_static{};
    const std::array<double, N> v{};
};

class X: Z<X>{};

С инициализацией N проблем не возникает

template<>
constexpr std::size_t Z<X>::N = 3;

Но как конкретизировать v и v_static для Z< X >? Следующий код не работает

template<>
std::array<int, Z<X>::N> Z<X>::v_static = { 4, 5, 6 };

template<>
const std::array<double, Z<X>::N> Z<X>::v = {3.14, 2.7, 0.1};

Ответы (1 шт):

Автор решения: isnullxbh

как исправить данный код, чтобы он компилировался?

Определить полную специализацию Z для X:

template<>
class Z<X>
{
    static constexpr std::size_t           N { 3 };
    static constexpr std::array<int, N>    v_static { 4, 5, 6 };
    const            std::array<double, N> v { 3.14, 2.7, 0.1 };
};

Но как конкретизировать v и v_static для Z< X >? Следующий код не работает

После того, как Вы дали определение X, компилятор уже сгенерировал специализацию Z<X>, и в этой специализации Z<X>::N все еще равен нулю, равно как и Z<X>::v_static имеет тип std::array<int, 0>. Когда Вы пытаетесь дать определение, после того, как изменили значение N, Вы фактически меняете тип v_static на std::array<int, 3>. Разумеется, это невозможно.

Что касается out-of-class определения template<> constexpr std::size_t Z<X>::N = 3;, оно у меня вызывает подозрения :) Давать out-of-class определение static constexpr члену-данных все еще можно (а иногда и нужно, зависит от стандарта C++), но без инициализатора, т.е.:

template<typename T>
constexpr std::size_t Z<T>::N;
→ Ссылка