Я знаю, что вопрос задавался несколько раз, и я читал сообщения типа:
Инициализация статических членов шаблонного класса
Как я могу объявить / определить / инициализировать статическую переменную-член классов шаблонов как статические переменные-члены класса?
статическая инициализация члена для специализированного шаблонного класса
Однако я все еще изо всех сил пытаюсь собрать воедино все, что касается шаблонов, специализаций, определения членов статических данных и объявлений.
То, что у меня есть, выглядит примерно так:
template<size_t dim>
struct A {
static std::array<float,dim> a1;
};
template<>
std::array<float,1U> A<1U>::a1{1.};
template<>
std::array<float,2U> A<2U>::a1{0.3,0.3};
int main() {
std::array<float, 1U> v1 = A<1U>::a1;
std::cout << v1[0] << std::endl;
std::array<float, 2U> v2 = A<2U>::a1;
std::cout << v2[0] << " " << v2[1] << std::endl;
return 0;
}
Этот код компилируетсяна обоих GCC 9.2.0 и MSVC2015. Теперь я понимаю, что нечто подобное, если оно будет включено несколько раз, может привести к нескольким определениям одной и той же статической переменной, поскольку у нас есть полная специализация шаблона. Таким образом, подход состоит в том, чтобы переместить это в файл cpp, но сохранить объявление специализации в hpp. Я сделаю это немного сложнее, добавив hpp-файл для реализации шаблона:
//foo.hpp
template<size_t dim>
struct A {
static std::array<float, dim> a1;
};
#include "fooImpl.hpp"
//fooImpl.hpp
template<>
std::array<float, 1U> A<1U>::a1;
template<>
std::array<float, 2U> A<2U>::a1;
//foo.cpp
#include"foo.hpp"
template<>
std::array<float, 1U> A<1U>::a1{ 1. };
template<>
std::array<float, 2U> A<2U>::a1{ 0.3,0.3 };
//main.cpp
int main() {
std::array<float, 1U> v1 = A<1U>::a1;
std::cout << v1[0] << std::endl;
std::array<float, 2U> v2 = A<2U>::a1;
std::cout << v2[0] << " " << v2[1] << std::endl;
return 0;
}
Этот код прекрасно компилируется на GCC9.2.0, но не работает на MSVC2015 из-за переопределения a1.
Как правильно это сделать? Почему MSVC жалуется? Есть ли способ сделать его корректным и переносимым для всех компиляторов, совместимых с c ++ 11?
ОБНОВЛЕНИЕ: Первый код не дает правильных результатов в MSVC и показывает только нули. Чтобы заставить его работать должным образом, мне нужно было убрать "template <>" из инициализации статического члена. Но это приводит к некомпиляции кода в GCC.
ОБНОВЛЕНИЕ 2: я нашел в основном тот же вопрос здесь с более полным анализом:
Разрешение определений специализированных переменных статического членашаблонных классов
Однако никто не ответил на этот вопрос.