dimanche 27 octobre 2019

Class template static data-member definition/declaration/initialization

I know that the question has been asked several times and I've been reading posts like:

Initializing static members of a templated class

How can I Declare/define/initialize a static member variable of template classes as static member variables of a class?

static member initialization for specialized template class

However, I'm still struggling putting together all the pieces about templates, specializations, static data members definition and declarations.

What I have is something like:


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::array<float,2U> v2 = A<2U>::a1;
    return 0;
}

This code compiles on both GCC 9.2.0 and MSVC2015. Now, my understanding is that something like this, if included multiple times, may lead to multiple definitions of the same static variable since we have a complete specialization of the template. So the approach is to move this to a cpp file but keep a declaration of the specialization in the hpp. I'll do it a little more complicate by also adding a hpp file for the template implementation:

//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;
}

This code compiles fine on GCC9.2.0 but fails on MSVC2015 because of a redefinition of a1.

What is the correct way to do this? Why MSVC is complaining? Is there a way to make it correct and portable for all c++11-compliant compilers?

Aucun commentaire:

Enregistrer un commentaire