无法声明静态constexpr char []

时间:2017-08-04 09:37:52

标签: c++ arrays c++11 static constexpr

我已经阅读了与此问题相关的所有答案,但老实说,我不确定我是否完全理解该解决方案。我正在使用C ++ 11。

让我们说我真的想宣布像static constexpr char value[] = "foo"这样的东西。

如果我使用NetBeans / TDM_MINGW,我会收到一个错误,我认为这是一个链接错误报告对“variable_name”的未定义引用

在MS VS 2015中尝试相同的代码我得到“表达式没有评估为常量”

一个简单的static constexpr char *解决了这个问题,但我无法使用像sizeof这样的表达式。

简单直接的问题(如果可能的话,直截了当的问题):

  1. 有没有办法在static constexpr char [] / struct内声明 class
  2. 如果1)是假的,是否有最清洁的解决方案可以解决这个问题?的 static constexpr char * ????
  3. 或旧的 static const char [] 仍是这种情况的最佳方法?
  4. 我测试过的解决方案虽然有效但远非“干净”static constexpr array<char,50> getConstExpr(){ return array<char,50> {"Hell"} }。它工作正常,但我必须声明char std::array的大小:(

3 个答案:

答案 0 :(得分:3)

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>{}); }

答案 1 :(得分:0)

如果你想避免C风格的数组,还有一个使用std :: string_view的C ++ 17解决方案......这要简单得多。 ;)

以下是perm-link以下代码。

#include <iostream>
#include <string_view>

int main ()
{
    constexpr std::string_view foo ( "Hell" );
    static_assert ( 4U == foo.size (), "!" );

    std::cout << "Done";
    return EXIT_SUCCESS;
}

答案 2 :(得分:0)

从C ++ 17开始,你不需要做任何特别的事情,因为static constexpr成员变量是隐含的inline

以下工作:

#include <iostream>

struct S
{
    static constexpr char value[] = "Meow!\n";
};

int main()
{
    std::cout << S::value;
}