Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot declare static constexpr char []

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) :

  1. Is there a way to declare a static constexpr char [] inside struct/class?
  2. If 1) is false is there a cleanest solution to overcome this? static constexpr char *????
  3. Or the old static const char [] is still the best approach for this case?
  4. I've tested a solution that works but far from being "clean" 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 :(
like image 410
Jacinto Resende Avatar asked Oct 18 '22 08:10

Jacinto Resende


1 Answers

1) Is there a way to declare a static constexpr char [] inside struct/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>{}); }
like image 110
max66 Avatar answered Oct 30 '22 03:10

max66