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

问题描述

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









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



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



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





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

解决方案

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



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

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

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

05-27 21:33
查看更多