是否可以为字符串文字创建模板化的用户定义文字(文字后缀)?

Hol*_*Cat 5 c++ templates c++11

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

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

// ...

std::cout << 123_s;
Run Code Online (Sandbox Code Playgroud)

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

"123"_s
Run Code Online (Sandbox Code Playgroud)

给我以下错误:

prog.cpp:在函数'int main()'中:
prog.cpp:12:15:错误:没有匹配的函数可调用'operator“” _ s()'
std :: cout <<“ 123” _s;

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

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

(爱迪生)

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

Hol*_*Cat 2

在 C++20 之前,这在标准 C++ 中是不可能的。请参阅@TC 的答案,了解适用于 GCC 和 Clang 的非标准解决方案。


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

#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);
    }
};
Run Code Online (Sandbox Code Playgroud)

它允许您执行以下操作:

#include <iostream>

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

int main()
{
    Print<"foo">();
}
Run Code Online (Sandbox Code Playgroud)

这可能足以满足您的用例,并且您可能不需要模板 UDL 本身。

但如果你确实需要它们,这是可能的:

#include <iostream>

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

int main()
{
    "foo"_print;
}
Run Code Online (Sandbox Code Playgroud)