简体   繁体   English

在类模板中使用条件运算符初始化静态constexpr char数组成员

[英]Initialize static constexpr char array member with conditional operator in class template

Consider a minimal example 考虑一个最小的例子

#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 ,
}

What I want to achieve is: 我想要实现的是:

  • if T has an integral type, then sep is initialized to . 如果T具有整数类型,则sep初始化为.
  • otherwise, sep is initialized to , 否则, sep初始化为,

However, the compiler won't allow this, saying 但是,编译器不允许这样做,

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

It looks like something must be done in compile time. 看来必须在编译时完成一些工作。 But I am not sure how to do it. 但是我不确定该怎么做。

My question is: is there anything I can do to achieve this end? 我的问题是: 我能做些什么来达到这个目的?

Note: Minimal change is most welcome. 注意:欢迎最小的更改。 There ought to be many other things in foo . foo应该还有许多其他内容。 Another consideration is that I want to keep everything about foo in header and to leave nothing in source file, if possible. 另一个考虑因素是,我想将有关foo所有内容保留在标头中,并在可能的情况下不保留任何源文件。

Thank you very much. 非常感谢你。

C-arrays are not copyable, so you have to work-around that C数组不可复制,因此您必须解决该问题

  • Do the check for each character: 对每个字符进行检查:

     constexpr char sep[3] = { std::is_integral<T>::value ? '.' : ',', ' ', '\\0' }; 
  • Don't use array but pointer (so you loose size): 不要使用数组,而是使用指针(这样就可以减小大小):

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

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

     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; 

    and provide definition of dot_sep / comma_sep which are ODR-used. 并提供ODR使用的dot_sep / comma_sep定义。

The best way is to use base class with specialization, and put sep in the base class: 最好的方法是将基类与专业化一起使用,并将sep放在基类中:

template <bool IsIntegral>
struct foo_base;

template<>
struct foo_base<true>
{
    static constexpr char sep[3] = ". ";
};

template<>
struct foo_base<false>
{
    static constexpr char sep[4] = ",  ";
};


template<typename T>
struct foo : foo_base<std::is_integral_v<T>>
{
    // many other things ...
};

But if you don't want others to access the base, you can use private inheritance: 但是,如果您不希望其他人访问该库,则可以使用私有继承:

template<typename T>
struct foo : private foo_base<std::is_integral_v<T>>
{
    using foo_base<std::is_integral_v<T>>::sep;
    // many other things ...
};

Edit 编辑

The advantage of this solution over using a std::array<char, 3> , is that this solution plays nicely with functions that accept a reference to C arrays of char. 与使用std::array<char, 3>相比,此解决方案的优势在于,该解决方案可以很好地与接受对char的C数组的引用的函数配合使用。 Neither storing const char* nor std::array<char, 3> have this capability. 存储const char*std::array<char, 3>都不具有此功能。

For example, if you have functions like: 例如,如果您具有以下功能:

template <std::size_t I>
constexpr int count_nuls(const char (&x)[I])
{
    // Can't use std::count, since it is not constexpr
    unsigned count = 0;
    for (auto ch: x)
        if (ch == '\0')
            ++count;
    return count;
}

This function can't be used with std::array , or with a const char * . 此函数不能与std::arrayconst char * If there are many functions like that, one may not want to upgrade all of them to std::array . 如果有很多类似的功能,则可能不希望将所有功能都升级到std::array For example, this function works perfectly in: 例如,此功能在以下情况下可以完美工作:

static constexpr unsigned nuls = count_nuls(foo<double>::sep);

But won't work (without further modification) with std::array<char, 3> . 但是不能与std::array<char, 3>一起使用(未经进一步修改)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM