类模板静态数据成员定义/声明/初始化

问题描述 投票:1回答:1

我知道这个问题已经问过几次了,我一直在读类似的文章:

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

但是,我仍在努力将模板,专业化,静态数据成员的定义和声明的所有内容组合在一起。

我有的东西像:


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:通过更完整的分析,我在这里发现了基本相同的问题:

Resolving Definitions of Specialized Static Member Variables of Templated Classes

但是没有人回答这个问题。

c++ c++11 template-specialization static-members
1个回答
0
投票
如果您专门研究整个课程,则可以在cpp中省略template<>的使用。

下面的代码似乎可以解决您的目标,它可以在MSVC(x86 V19.14),gcc(x86-64 9.2)和clang(x86-64 9.0.0)as tested on Compiler Explorer上编译:

template<size_t dim> struct A { static std::array<float,dim> a1; }; template<> struct A<1U> { static std::array<float,1U> a1; }; template<> struct A<2U> { static std::array<float,2U> a1; }; // cpp std::array<float,1U> A<1U>::a1 {1.f}; std::array<float,2U> A<2U>::a1 {0.3f,0.3f}; 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; }

为什么cpp中的定义不需要模板<>?

根据17.7.3 [temp.expl.spec]第5段(N4659),

[...]显式专门的类模板的成员在与普通班级成员的方式相同,但不使用template <>语法。当定义一个成员时也是如此明确专门的成员类。 [...]

[Note

,这并不是说问题中的代码是错误的,但是由于MSVC不满意(并且可能是错误的……?),因此,解决方法可能是上面建议的代码。] >
© www.soinside.com 2019 - 2024. All rights reserved.