首页 > 解决方案 > 在类模板中使用条件运算符初始化静态 constexpr char 数组成员

问题描述

考虑一个最小的例子

#include <iostream>

template<typename T>
struct foo
{
    // won't compile. how to change?
    static constexpr char sep[3] = std::is_integral<T>::value ? ". " : ", ";

    // many other things ...
};

int main()
{
    std::cout << foo<int>::sep << std::endl;     // prints .
    std::cout << foo<double>::sep << std::endl;  // prints ,
}

我想要实现的是:

但是,编译器不允许这样做,说

error: array must be initialized with a brace-enclosed initializer

看起来必须在编译时完成一些事情。但我不知道该怎么做。

我的问题是:我能做些什么来达到这个目的吗?

注意:欢迎进行最小的更改。里面应该还有很多其他的东西foo。另一个考虑因素是,如果可能的话,我想将所有内容都保留foo在标头中,并且在源文件中不留下任何内容。

非常感谢。

标签: c++initializationconstexpr

解决方案


C 数组是不可复制的,所以你必须解决这个问题

  • 检查每个字符:

    constexpr char sep[3] = { std::is_integral<T>::value ? '.' : ',', ' ', '\0' };
    
  • 不要使用数组,而是使用指针(所以你会丢失大小):

    constexpr const char* sep = std::is_integral<T>::value ? ". " : ", ";
    
  • 使用std::array

    constexpr std::array<char, 3> sep = std::is_integral<T>::value
       ? std::array<char, 3>{{'.', ' ', 0}}
       : std::array<char, 3>{{',', ' ', 0}};
    
  • 使用对数组的引用:

    constexpr char dot_sep[3] = std::is_integral<T>::value ? ". " : ", ";
    constexpr char comma_sep[3] = std::is_integral<T>::value ? ". " : ", ";
    constexpr const char (&sep)[3] = std::is_integral<T>::value ? dot_sep : comma_sep;
    

    并提供ODR 使用的dot_sep/的定义。comma_sep


推荐阅读