是否可以为字符串文字创建模板化的用户定义文字(文字后缀)? [英] Is it possible to create templated user-defined literals (literal suffixes) for string literals?

查看:33
本文介绍了是否可以为字符串文字创建模板化的用户定义文字(文字后缀)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我发现可以将用户定义的文字模板化时,我感到很惊讶:

I was suprised when I discovered that it's possible to make user-defined literals templated:

template <char ...C> std::string operator ""_s()
{
    char arr[]{C...};
    return arr;
}

// ...

std::cout << 123_s;

但以上声明不适用于字符串文字:

But above declaration does not work with string literals:

"123"_s

给我以下错误:

prog.cpp: 在函数int main()"中:
prog.cpp:12:15: 错误:没有用于调用operator"_s()"的匹配函数
std::cout <<"123"_s;

prog.cpp: In function 'int main()':
prog.cpp:12:15: error: no matching function for call to 'operator""_s()'
std::cout << "123"_s;

prog.cpp:4:34: 注意:候选:模板 std::string operator""_s()
模板 std::string 运算符 ""_s()

prog.cpp:4:34: note: candidate: template std::string operator""_s()
template std::string operator ""_s()

prog.cpp:4:34: 注意:模板参数推导/替换失败:

prog.cpp:4:34: note: template argument deduction/substitution failed:

(Ideone)

有没有办法将模板化的用户定义文字也与字符串文字一起使用?

Is there is a way to use templated user-defined literals with string literals as well?

推荐答案

Pre-C++20 在标准 C++ 中是不可能的.有关适用于 GCC 和 Clang 的非标准解决方案,请参阅@T.C. 的答案.

Pre-C++20 it's impossible in standard C++. Refer to @T.C.'s answer for a non-standard solution that works with GCC and Clang.

从 C++20 开始,您可以将字符串文字作为模板参数传递.你需要一个这样的辅助类:

Starting with C++20, you can pass string literals as template parameters. You need a helper class like this one:

#include <algorithm>
#include <cstddef>
#include <string_view>

namespace impl
{
    // Does nothing, but causes an error if called from a `consteval` function.
    inline void ExpectedNullTerminatedArray() {}
}

// A string that can be used as a template parameter.
template <std::size_t N>
struct ConstString
{
    char str[N]{};

    static constexpr std::size_t size = N - 1;

    [[nodiscard]] std::string_view view() const
    {
        return {str, str + size};
    }

    consteval ConstString() {}
    consteval ConstString(const char (&new_str)[N])
    {
        if (new_str[N-1] != '\0')
            impl::ExpectedNullTerminatedArray();
        std::copy_n(new_str, size, str);
    }
};

它允许你这样做:

#include <iostream>

template <ConstString S>
void Print()
{
    std::cout << S.view() << '\n';
}

int main()
{
    Print<"foo">();
}

这对于您的用例来说可能就足够了,而且您可能不需要模板 UDL 本身.

This might be enough for your use case, and you might not need template UDLs per se.

但如果您确实需要它们,那是可能的:

But if you do need them, it's possible:

#include <iostream>

template <ConstString S>
void operator""_print()
{
    std::cout << S.view();
}

int main()
{
    "foo"_print;
}

这篇关于是否可以为字符串文字创建模板化的用户定义文字(文字后缀)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆