C++ 具名要求:字面类型 (LiteralType) (C++11 起)
来自cppreference.com
指明一个类型为字面类型。字面类型是 constexpr
变量拥有的类型,且能通过 constexpr
函数构造、操作及返回它们。
注意:标准中并没有定义具有这个名字的具名要求。这是核心语言所定义的一种类型类别。将它作为具名要求包含于此只是为了保持一致性。
要求
字面类型是下列之一:
|
(C++14 起) |
- 拥有平凡 (C++20 前)
constexpr
(C++20 起)析构函数, - 其所有非静态非可变数据成员和基类都是非 volatile 字面类型,并且
- 是以下之一:
- 拥有平凡 (C++20 前)
(C++17 起) |
注解
字面类型的构造函数可以都被弃置、不可访问或不参与重载决议。
struct A { constexpr A(int) = delete; char c; }; // A 是字面类型 constexpr A v = std::bit_cast<A>('0'); // C++20 起 OK // v 拥有字面类型因此可以是 constexpr 的
示例
扩展字符串字面量的字面类型:
运行此代码
#include <cstddef> #include <iostream> #include <stdexcept> class conststr // conststr 是字面类型 { const char* p; std::size_t sz; public: template<std::size_t N> constexpr conststr(const char(&a)[N]) : p(a), sz(N - 1) {} constexpr char operator[](std::size_t n) const { return n < sz ? p[n] : throw std::out_of_range(""); } constexpr std::size_t size() const { return sz; } }; constexpr std::size_t count_lower(conststr s) { std::size_t c{}; for (std::size_t n{}; n != s.size(); ++n) if ('a' <= s[n] && s[n] <= 'z') ++c; return c; } // 要求编译时常量 N 的输出函数,测试需要 template<int N> struct constN { constN() { std::cout << N << '\n'; } }; int main() { std::cout << "\"Hello, world!\" 中小写字母的个数是 "; constN<count_lower("Hello, world!")>(); // 字符串字面量被隐式转换成 conststr }
输出:
"Hello, world!" 中小写字母的个数是 9
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
CWG 1453 | C++11 | 字面类可以有 volatile 数据成员 | 已禁止 |
CWG 1951 | C++11 C++14 |
未指明有 cv 限定的 void (C++14)和类类型(C++11)是不是字面类型 |
它们是 |
CWG 2096 | C++11 | 联合体类型只有在所有非静态数据 成员都是字面类型时才是字面类型 |
只需要有一个非静态 数据成员是字面类型 |
CWG 2598 | C++11 | 联合体类型只有在至少有一个 非静态数据成员时才是字面类型 |
也可以没有静态数据成员 |
参阅
(C++11)(C++17 中弃用)(C++20 中移除) |
检查类型是否为字面类型 (类模板) |