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:
T
has an integral type, then sep
is initialized to .
sep
is initialized to ,
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
. Another consideration is that I want to keep everything about foo
in header and to leave nothing in source file, if possible.
Thank you very much.
C-arrays are not copyable, so you have to work-around that
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
:
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.