Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 字符数组何时是常量表达式?_C++_Boost_Template Meta Programming_Boost Hana - Fatal编程技术网

C++ 字符数组何时是常量表达式?

C++ 字符数组何时是常量表达式?,c++,boost,template-meta-programming,boost-hana,C++,Boost,Template Meta Programming,Boost Hana,我一直在使用Boost.Hana生成编译时字符串,用作gcc的模板参数: using namespace boost::hana::literals; #define GQL_STR(tok) decltype(#tok ## _s) 它依赖于设置BOOST\u HANA\u CONFIG\u ENABLE\u STRING\u UDLdefine。然而,我的代码应该是可移植的,这依赖于gcc/clang扩展。在阅读了这篇伟大的文章后,我写了一篇文章,用Boost.Mp11来模拟它,只是稍微有

我一直在使用Boost.Hana生成编译时字符串,用作gcc的模板参数:

using namespace boost::hana::literals;
#define GQL_STR(tok) decltype(#tok ## _s)
它依赖于设置
BOOST\u HANA\u CONFIG\u ENABLE\u STRING\u UDL
define。然而,我的代码应该是可移植的,这依赖于gcc/clang扩展。在阅读了这篇伟大的文章后,我写了一篇文章,用Boost.Mp11来模拟它,只是稍微有点额外的方便:

#include <boost/mp11/list.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/hana/string.hpp>
#include <boost/preprocessor/config/limits.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>

#include <iostream>

namespace
{
template <int N>
constexpr char get(const char(&str)[N], int i)
{
    return i < N ? str[i] : '\0';
}

struct is_null_char
{
    template <typename T>
    using fn = std::is_same<std::integral_constant<char, '\0'>, T>;
};

template <char... Cs>
constexpr auto list_to_string(boost::mp11::mp_list_c<char, Cs...>)
{
    return boost::hana::string<Cs...>{};
}

template <char... Cs>
struct builder
{
    using strip_null = boost::mp11::mp_remove_if_q<
        boost::mp11::mp_list_c<char, Cs...>,
        is_null_char
    >;

    using type = decltype(list_to_string(strip_null{}));
};

#define GQL_STR_CHAR(z, n, tok) \
    BOOST_PP_COMMA_IF(n) get(tok, n)

#define GQL_STR_N(n, tok) \
    typename builder<BOOST_PP_REPEAT(n, GQL_STR_CHAR, tok)>::type
}

#define GQL_STR(tok) GQL_STR_N(128, #tok)

int main()
{
    using hello_s = GQL_STR(hello);

    std::cout << hello_s{}.c_str() << std::endl;
    return EXIT_SUCCESS;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
名称空间
{
模板
constexpr char get(const char(&str)[N],int i)
{
返回i;
使用type=decltype(list_to_string(strip_null{}));
};
#定义GQL_STR_CHAR(z,n,tok)\
如果(n)get(tok,n),则BOOST_PP_逗号_
#定义GQL_STR_N(N,tok)\
typename生成器::类型
}
#定义GQL_STR(tok)GQL_STR_N(128,#tok)
int main()
{
使用hello_s=GQL_STR(hello);

std::难道这一切都可以归结为一个简单的事实,即函数参数从来都不是常量表达式。我会尝试找到一个重复,我知道有几个。这是我能找到的最接近的一个:@NathanOliver,啊,所以第一个代码示例也不应该工作,但可能编译器正在做一些事情来允许它。第一个代码工作,因为您不要试图在常量表达式中使用关于
str
的任何内容。
返回i
可以在编译时和运行时运行。OTOH
返回boost::hana::string{};
只能在编译时完成,但在运行时调用constexpr函数是合法的,因此不允许这样做。但我确实在常量表达式中使用它,它的元素被访问以创建一个返回值,该返回值被放入模板值参数中。这一切归结为一个简单的事实,即函数参数从来都不是常量t表达式。我会尝试找到一个重复,我知道有一些。这是我能找到的最接近的一个:@NathanOliver,啊,所以第一个代码示例也不应该工作,但可能编译器正在做一些事情来允许它。第一个代码工作,因为您不尝试在常量表达式中使用任何关于
str
返回I
可以在编译时和运行时运行。OTOH
返回boost::hana::string{};
只能在编译时完成,但在运行时调用constexpr函数是合法的,因此不允许这样做。但我确实在常量表达式中使用它,它的元素被访问以创建一个返回值,该返回值被放入模板值参数中。
namespace
{
template <int N, int... I>
constexpr auto gql_str_impl(const char(&str)[N], std::integer_sequence<int, I...>)
{
    return boost::hana::string<str[I]...>{};
}

template <int N>
constexpr auto gql_str(const char(&str)[N])
{
    return gql_str_impl(str, std::make_integer_sequence<int, N-1>{});
}
}

#define GQL_STR(tok) \
    decltype(gql_str(#tok))
<source>:15:43: error: 'str' is not a constant expression
   15 |     return boost::hana::string<str[I]...>{};
typename builder<get("hello", 0), get("hello", 1), ...>::type