类模板静态数据成员的定义/声明/初始化 [英] Class template static data-member definition/declaration/initialization

查看:172
本文介绍了类模板静态数据成员的定义/声明/初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题已经问过几次了,我一直在阅读以下文章:



初始化模板化类的静态成员



如何声明/定义/初始化静态成员模板类的变量作为类的静态成员变量?





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



我所拥有的类似于:

  
template< size_t dim>
struct A {
static std :: array< float,dim> a1;
};

模板<>
std :: array< float,1U> A< 1U> :: a1 {1。};

模板<>
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;
返回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.};

模板<>
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;
返回0;
}

此代码在GCC9.2.0上编译良好,但在MSVC2015上由于重新定义而失败

执行此操作的正确方法是什么?为什么MSVC抱怨?有没有一种方法可以使它对于所有与c ++ 11兼容的编译器都是正确且可移植的?



更新:
第一个代码未提供正确的结果MSVC,它只显示零。为了使其正常工作,我需要从静态成员的初始化中删除 template<>。但这会导致GCC中的未编译代码。



更新2:
我在这里发现了基本相同的问题,并进行了更完整的分析:



解析模板类的专用静态成员变量的定义



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

解决方案

您点击 MSVC中的错误。显然,它已在 Visual Studio 2019版本16.5 Preview 2 中得到修复。



作为替代解决方案,您可以将定义保留在标题和将它们标记为内联(自c ++ 17 起):

  template<> 
内联std :: array< float,1U> A< 1U> :: a1 {1。};

模板<>
内联std :: array< float,2U> A 2U :: a1 {0.3,0.3};


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::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 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?

UPDATE: The first code does not provide right results on MSVC and it only shows zeros. In order to make it work properly I needed to take away "template<>" from the initialization of the static member. But this leads to non-compiling code in GCC.

UPDATE 2: I found basically the same question in here with a more complete analysis:

Resolving Definitions of Specialized Static Member Variables of Templated Classes

However nobody answered that question.

解决方案

You hit a bug in MSVC. It has apparently been fixed in Visual Studio 2019 version 16.5 Preview 2.

As an alternative workaround, you could leave your definitions in the header and mark them as inline (since c++17):

template<> 
inline std::array<float,1U> A<1U>::a1{1.};

template<> 
inline std::array<float,2U> A<2U>::a1{0.3,0.3};

这篇关于类模板静态数据成员的定义/声明/初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆