【发布时间】:2019-10-27 20:21:36
【问题描述】:
我知道这个问题已经被问过好几次了,我一直在阅读以下帖子:
Initializing static members of a templated 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.xml 中保留专业化声明。我将通过为模板实现添加一个 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