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 的
示例
扩展字符串字面量的字面类型:
Run this code
#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 移除) |
检查类型是否为字面类型 (类模板) |