gre*_*ekd 2 c++ gcc clang user-defined-literals c++20
我正在尝试定义用户定义的字符串文字模板。
该代码片段不应该起作用吗?/ 为什么不起作用?
template<char...>
constexpr
int operator ""_x () {
return 0;
}
int x = "abc"_x;
Run Code Online (Sandbox Code Playgroud)
运算符声明被编译器“接受”为有效 - C++ 对用户定义的文字非常严格,任何与规范声明的偏差都会被诊断为错误。因此,接受该声明对我来说表明它很好 - 正如我所期望的 - 但我尝试过的编译器(GCC、Clang、MSVC - godbolt.org 上的所有trunk)都没有编译使用下一个定义运算符,其中 Clang 和 MSVC 找不到匹配的文字运算符,而 GCC 给出了一个令人惊讶的奇怪错误(你可以在godbolt.org上看到完整的错误),其中部分:
(...)
<source>:7:9: error: type/value mismatch at argument 1 in template parameter list for 'template<char ...<anonymous> > constexpr int operator""_x()'
7 | int x = "abc"_x;
| ^~~~~~~
<source>:7:9: note: expected a constant of type 'char', got 'char'
Run Code Online (Sandbox Code Playgroud)
(编译器说)我预料到了char,但是我得到了char......Maaan......我不知道现在该怎么办!- 最令人困惑的...
我在这个项目中使用 Clang 15,因此如果有针对此问题的编译器特定修复程序,我将不胜感激。
编辑:根据第一个答案 - 我必须补充一点,这是显示问题的最小片段,而不是该函数的目标用例 - 它是一个模板至关重要 - 更具体地说:我想实现多 -字符文字运算符,但不幸的是,定义 C++ 规范的人决定禁止int16/int32类型被接受为用户定义的文字参数,它们是 Clang 的 'ab'/'abc'/'abcd' 的基础类型,我决定将其通过使用字符串文字(“”)而不是字符一('')来解决,但为了使其工作,我需要在编译时限制源字符串文字的可接受长度,(据我所知)仅当文字作为模板参数传递时,才可以在 C++ 中使用。
在这种情况下,您不需要模板。
#include <string>
constexpr int operator""_x (const char* str, std::size_t) {
return 0;
}
int x = "abc"_x;
Run Code Online (Sandbox Code Playgroud)
模板用于转换字符串文字以外的文字:
template<char...>
constexpr
int operator ""_x () {
return 0;
}
int x = 10_x;
Run Code Online (Sandbox Code Playgroud)
根据问题中的新信息,限制可接受的字符串文字长度:
#include <string>
template<std::size_t N>
struct StringLiteral {
char s[N]{};
constexpr StringLiteral(char const(&p)[N]) {
// restrict the acceptable length with 4 chars + terminator
static_assert(N <= 5);
std::copy(p, p + N, s);
}
};
template<StringLiteral L>
constexpr int operator""_x() {
// Use L.s
return 0;
}
int x = "abc"_x;
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/nvj1GGjbM
或者使结构与字符串文字长度无关:
#include <string>
template<std::size_t N>
struct StringLiteral {
char s[N]{};
std::size_t n{};
constexpr StringLiteral(char const(&p)[N]) : n(N) {
std::copy(p, p + N, s);
}
};
template<StringLiteral L>
constexpr int operator""_x() {
// restrict the acceptable length with 4 chars + terminator
static_assert(L.n <= 5);
// Use L.s
return 0;
}
int x = "abc"_x;
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/hdP4aoefn
| 归档时间: |
|
| 查看次数: |
176 次 |
| 最近记录: |