I've read all the answers related with this issue but honestly I'm not sure if I've fully understand the solution. I'm using C++11.
Lets say I really would like to declare something like static constexpr char value[] = "foo"
.
If I use NetBeans/TDM_MINGW I get an error which I suppose is a link error reporting undefined reference to "variable_name".
Trying the same code in MS VS 2015 I get "expression did not evaluate to a constant".
A simple static constexpr char *
solves the problem but I lost the ability of using expressions like sizeof
.
Simple and straightforward questions (if possible straightforward anwsers) :
static constexpr char []
inside struct
/class
?static constexpr char *
????static const char []
is still the best approach for this case?static constexpr array<char,50> getConstExpr(){
return array<char,50> {"Hell"}
}
. It works fine but I have to declare the size of the char std::array
:(1) Is there a way to declare a
static constexpr char []
insidestruct
/class
?
Yes; it's simple.
The following is a full working example
struct bar
{ static constexpr char value[] = "foo"; };
constexpr char bar::value[];
int main ()
{
std::cout << bar::value << std::endl; // print foo
}
I suppose You forgot the bar::value[]
row.
2) If 1) is false is there a cleanest solution to overcome this
static constexpr char *
????
Not applicable.
3) Or the old
static const char []
is still the best approach for this case?
Depend from the problem you have to solve; but usually I suggest to avoid C-style arrays and use the new C++11 std::array
4) I've tested a solution that works but far from being "clean" [...] It works fine but I have to declare the size of the char
std::array
:(
I propose you a solution (unfortunately work starting from C++14, but isn't too difficult make a C++11 version) to detect the correct size from "Hell"
passed as parameter.
Observe the use of std::make_index_sequence
and std::index_sequence
to pass the single chars from the char[]
variable to the std::array
.
template <std::size_t Dim, std::size_t ... Is>
constexpr std::array<char, Dim> gceH (char const (&str)[Dim],
std::index_sequence<Is...> const &)
{ return { { str[Is]... } }; }
template <std::size_t Dim>
constexpr std::array<char, Dim> getConstExpr (char const (&str)[Dim])
{ return gceH(str, std::make_index_sequence<Dim>{}); }
int main ()
{
constexpr auto f = getConstExpr("Hell");
static_assert( 5U == f.size(), "!" );
}
-- EDIT --
As suggested by Swift (thanks!) using a template type, instead char
, transform getConstExpr()
in a more flexible function.
So getConstExpr()
and the helper function (gceH()
) can be written as follows
template <typename T, std::size_t Dim, std::size_t ... Is>
constexpr std::array<T, Dim> gceH (T const (&str)[Dim],
std::index_sequence<Is...> const &)
{ return { { str[Is]... } }; }
template <typename T, std::size_t Dim>
constexpr std::array<T, Dim> getConstExpr (T const (&str)[Dim])
{ return gceH(str, std::make_index_sequence<Dim>{}); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With