另一个字符串文字,UDL 迷宫

Posted

技术标签:

【中文标题】另一个字符串文字,UDL 迷宫【英文标题】:Yet another string literal, UDL labyrinth 【发布时间】:2019-08-19 07:10:36 【问题描述】:

注意:这是 MSVC,C++17 问题。

免责声明:我知道这已经尝试过了,是的,我试图找到相关的 SO 答案。

我可以编写UDL,以实现在编译时将数字文字转换为std::array

    // std::array '1','2','3' 
    constexpr auto a_1 = 123_std_char_array;

    // std::array '0','x','1','2' 
    constexpr auto a_2 = 0x12_std_char_array;

    // std::array '4'.'2','.','1','3' 
    constexpr auto a_3 = 42.13_std_char_array;

这是我制作的 UDL:

    template< char ... Chs >
inline constexpr decltype(auto) operator"" _std_char_array( )

    // append '\0'
    return  std::array  Chs..., char(0)  ;

惊人的,时髦的,现代的,等等,等等,等等……但是。

问题

我如何编写一个 UDL 来实现这一点:

    // std::array 'S','t','r','i','n','g'
    constexpr auto std_char_array_buff_ = 
         "String"_std_char_array ;

请在 MSVC 中使用 C++17。

忏悔

我知道要“捕获”字符串文字的 UDL 必须有这个足迹:

  inline auto operator"" _X( const char*, size_t);

我知道如何在编译时将字符串文字转换为 std::array。但是没有UDL。 Please see here,求灵感。

是的,我知道 C++20 将添加 UDL 模板,而 GCC、clang 现在还有其他东西。虽然我看不出这对我有什么帮助。

最后,我知道我可以做到:

     constexpr auto string_view_ = "String"sv ;

【问题讨论】:

我知道如何在编译时将字符串文字转换为 std::array。但是没有 UDL。 为什么不能直接从 UDL 调用 that?除非您的意思是转换 const char[N] 而不是 const char*std::size_t @Zereges,请告诉我们你会如何做到这一点? @ChefGladiator,Zerege 可能在谈论to_array 是如何实现的,使用const char (&amp;)[N] 参数,推导出模板参数N,它既不是UDL 的有效参数,也不能从const char*size_t,即使 size_t 的值在编译时是已知的。 @JoelFilho 没错。这是 code 有趣的 MSVC 失败。 @JoelFilho 是的,我明白 Zereges 在说什么。唉,我有点困惑,这对我们有什么帮助?我相信我们中的许多人使用这种代码已经很长时间了。而且我知道不能像 Zerges 建议的那样以某种方式“从 UDL 调用”。很抱歉直言不讳。 【参考方案1】:

不幸的是,这在 C++17 中似乎是不可能的。 user-defined-string-literal 只能匹配每个 [lex.ext]/5 的 operator""X(str, len)。那么len是一个函数参数,函数参数不能转换为模板参数。就像你不能这样做:

template <int N>
struct S ;

constexpr auto f(int n)

    return S<n>; // no, n is not guaranteed to be known at compile time

"foo"sv 之所以有效,是因为大小不是std::basic_string_view 的模板参数,而是一个“运行时”属性,它恰好受益于constexpr。你不能用std::array来做,因为大小是std::array的模板参数。

make_array 之所以有效,是因为它不是文字运算符,因此它可以将大小作为 template 参数而不是 function 参数。然后,它可以将模板参数传递给std::array。文字运算符无法做到这一点。


在 C++20 中,我认为我们可以使用这样的包装器类型:

template <std::size_t N>
struct helper 
    std::array<char, N> string;

    template <std::size_t... Is>
    constexpr helper(const char (&str)[N + 1], std::index_sequence<Is...>)
        :stringstr[Is]...
    
    
    constexpr helper(const char (&str)[N + 1])
        :helperstr, std::make_index_sequence<N>
    
    
;

template <std::size_t N>
helper(const char (&str)[N]) -> helper<N - 1>;

然后使用字符串文字操作符模板:

template <helper str> // placeholder type for deduction
constexpr auto operator""_S()

    return str.string;


static_assert("foo"_S == std::array'f', 'o', 'o');

C++20 还没有最终确定,所以我不能确定。

【讨论】:

谢谢。是的,这就是(大约)C++2x 的帮助方式。希望这将在 C++20 中被“投票”。一个反驳的论点,我实际上记得读过这可能“给编译器供应商带来压力”。如果我没记错的话,假设是该功能可能允许某些人以这种方式创建“大量文本”。但是,这我们已经可以做到了。不确定不向 UDL 提供接收本机数组引用的简单签名的目的是什么/目的是什么,例如,自 C++11 起 @ChefGladiator 我认为这是当前草案所说的,所以它可能已经被投票了。此外,如果你觉得它有用,你可以投票(并选择接受它),以防万一你不知道。

以上是关于另一个字符串文字,UDL 迷宫的主要内容,如果未能解决你的问题,请参考以下文章

链接数据库都有哪些方法?

如何将字符串文字类型定义为另一个字符串文字类型的子类型?

如何正确获取MYSQL的ADO连接字符串

如何获取SQL server数据库的连接字符串

在VC中创建Mysql数据库

分享一个golang数据结构相关的文字迷宫小游戏