gpt4 book ai didi

c++ - MPL 序列 : is this legal? 的用户定义文字

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:40:30 25 4
gpt4 key购买 nike

能够将传递给文字运算符的字符串转换为 MPL 序列会很有用,因为这样我们就可以根据字符串的内容控制代码生成。以前,我认为这是不可能的,因为 constexpr 函数的参数在函数体内不被视为常量表达式。但是,我想出了以下在 Clang 3.4.2 和 GCC 4.8.2 下编译的解决方法:

#include <cstdint>
#include <iostream>
#include <typeinfo>

struct string
{
const uintmax_t m_str[64];
const size_t m_length;

template <class... Ts>
constexpr string(const Ts... ts) :
m_str{(uintmax_t)ts...}, m_length{sizeof...(Ts)} {}

constexpr size_t size() const { return m_length; }
constexpr size_t length() const { return m_length; }
constexpr uintmax_t operator[](size_t n) const { return m_str[n]; }
};

template <uintmax_t... Ts> struct sequence {};

constexpr auto
operator"" _tag(const char* str, size_t n)
{
return n == 0 ? string{} :
n == 1 ? string{str[0]} :
n == 2 ? string{str[0], str[1]} :
n == 3 ? string{str[0], str[1], str[2]} :
n == 4 ? string{str[0], str[1], str[2], str[3]} :
n == 5 ? string{str[0], str[1], str[2], str[3], str[4]} :
string{str[0], str[1], str[2], str[3], str[4], str[5]};
}

int main()
{
static constexpr auto string = "Hello!"_tag;
using sequence = sequence<string[0], string[1], string[2], string[3], string[4], string[5]>;
std::cout << typeid(sequence{}).name() << std::endl;
}

输出:

sequence<72ul, 101ul, 108ul, 108ul, 111ul, 33ul>

问题

这段代码是否调用了未定义的行为,或者它是否合法?

最佳答案

这是正确的。除非必要,否则条件运算符不会评估操作数。

不过你做的太复杂了。尝试使用 string literal operator templates (Clang 和 GCC 都支持)。它们最初是为 C++1Y 计划的——尽管该提议被拒绝了(不知道为什么,它是由 Richard Smith 完成的,并且该功能是必不可少的)。

如果这不够便携(因为它现在只是编译器扩展),您可以使用二进制递归宏和 rtrim 类模板,例如 VTMPL :

# define VTMPL_SPLIT_1(s, x) ( x < sizeof(s) ? s[x] : decltype(*s)() )
# define VTMPL_SPLIT_4(s, x) VTMPL_SPLIT_1 (s, x), VTMPL_SPLIT_1 (s, x+1) , VTMPL_SPLIT_1 (s, x+2) , VTMPL_SPLIT_1 (s, x+3)
# define VTMPL_SPLIT_16(s, x) VTMPL_SPLIT_4 (s, x), VTMPL_SPLIT_4 (s, x+4) , VTMPL_SPLIT_4 (s, x+8) , VTMPL_SPLIT_4 (s, x+12)
# define VTMPL_SPLIT_64(s, x) VTMPL_SPLIT_16 (s, x), VTMPL_SPLIT_16 (s, x+16) , VTMPL_SPLIT_16 (s, x+32) , VTMPL_SPLIT_16 (s, x+48)
# define VTMPL_SPLIT_256(s, x) VTMPL_SPLIT_64 (s, x), VTMPL_SPLIT_64 (s, x+64) , VTMPL_SPLIT_64 (s, x+128), VTMPL_SPLIT_64 (s, x+194)
# define VTMPL_SPLIT_1024(s, x) VTMPL_SPLIT_256(s, x), VTMPL_SPLIT_256(s, x+256), VTMPL_SPLIT_256(s, x+512), VTMPL_SPLIT_256(s, x+768)

# define VTMPL_STRING_IMPL(str, n) vtmpl::rtrim<vtmpl::string<VTMPL_SPLIT_##n(str, 0)>>::type

# define VTMPL_STRING(str) VTMPL_STRING_IMPL(str, 64)
# define VTMPL_STRING_256(str) VTMPL_STRING_IMPL(str, 256)
# define VTMPL_STRING_1024(str) VTMPL_STRING_IMPL(str, 1024)

关于c++ - MPL 序列 : is this legal? 的用户定义文字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25701846/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com