跳到主要内容

C++ 命名要求:LiteralType (自 C++11 起)

指定一个类型是字面类型。字面类型是 constexpr 变量的类型,它们可以从 constexpr 函数中构造、操作和返回。

注意:标准没有定义具有此名称的命名要求。这是由核心语言定义的一种类型类别。为了保持一致性,此处将其作为命名要求包含。

要求

字面类型是以下之一

  • 可能带有 cv 限定符的 void(这样 constexpr 函数可以返回 void); (自 C++14 起)
  • 标量类型;
  • 引用类型;
  • 字面类型的数组
  • 可能带有 cv 限定符的类类型,具有以下所有属性
    • 具有一个 平凡的 (直到 C++20) constexpr (自 C++20 起) 析构函数
    • 是以下之一
      • 闭包类型 (自 C++17 起),
      • 聚合联合类型,并且
      • 没有变体成员,或者
      • 至少有一个非 volatile 字面类型的变体成员,
    • 非联合聚合类型,以及其每个匿名联合成员
      • 没有变体成员,或者
      • 至少有一个非 volatile 字面类型的变体成员,
    • 具有至少一个 constexpr(可能是模板)构造函数,且不是复制或移动构造函数的类型,

备注

即使其所有 constexpr 构造函数都被删除、不可访问或无法参与重载解析,类型也可以是字面类型。

struct A { constexpr A(int) = delete; char c; };    // A is a literal type
constexpr A v = std::bit_cast<A>('0'); // OK in C++20
// v has literal type and thus can be constexpr

示例

扩展字符串字面量的字面类型

#include <cstddef>
#include <iostream>
#include <stdexcept>

class conststr // conststr is a literal type
{
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;
}

// An output function that requires a compile-time constant N, for testing
template<int N>
struct constN
{
constN() { std::cout << N << '\n'; }
};

int main()
{
std::cout << "the number of lowercase letters in \"Hello, world!\" is ";
constN<count_lower("Hello, world!")>(); // the string literal is implicitly
// converted to conststr
}
结果
the number of lowercase letters in "Hello, world!" is 9

缺陷报告

以下改变行为的缺陷报告已追溯应用于先前发布的 C++ 标准。

DR应用于发布时的行为正确行为
CWG 1453C++11字面类可以有 volatile 数据成员不允许
CWG 1951C++11 C++14不清楚带有 cv 限定符的 void(C++14)和类类型(C++11)是否是字面类型它们是
CWG 2096C++11对于联合类型要成为字面类型,其所有非静态数据成员都必须是字面类型只需要一个非静态数据成员
CWG 2598C++11对于联合类型要成为字面类型,它必须至少有一个非静态数据成员它可以没有非静态数据成员

C++ 命名要求:LiteralType (自 C++11 起)

指定一个类型是字面类型。字面类型是 constexpr 变量的类型,它们可以从 constexpr 函数中构造、操作和返回。

注意:标准没有定义具有此名称的命名要求。这是由核心语言定义的一种类型类别。为了保持一致性,此处将其作为命名要求包含。

要求

字面类型是以下之一

  • 可能带有 cv 限定符的 void(这样 constexpr 函数可以返回 void); (自 C++14 起)
  • 标量类型;
  • 引用类型;
  • 字面类型的数组
  • 可能带有 cv 限定符的类类型,具有以下所有属性
    • 具有一个 平凡的 (直到 C++20) constexpr (自 C++20 起) 析构函数
    • 是以下之一
      • 闭包类型 (自 C++17 起),
      • 聚合联合类型,并且
      • 没有变体成员,或者
      • 至少有一个非 volatile 字面类型的变体成员,
    • 非联合聚合类型,以及其每个匿名联合成员
      • 没有变体成员,或者
      • 至少有一个非 volatile 字面类型的变体成员,
    • 具有至少一个 constexpr(可能是模板)构造函数,且不是复制或移动构造函数的类型,

备注

即使其所有 constexpr 构造函数都被删除、不可访问或无法参与重载解析,类型也可以是字面类型。

struct A { constexpr A(int) = delete; char c; };    // A is a literal type
constexpr A v = std::bit_cast<A>('0'); // OK in C++20
// v has literal type and thus can be constexpr

示例

扩展字符串字面量的字面类型

#include <cstddef>
#include <iostream>
#include <stdexcept>

class conststr // conststr is a literal type
{
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;
}

// An output function that requires a compile-time constant N, for testing
template<int N>
struct constN
{
constN() { std::cout << N << '\n'; }
};

int main()
{
std::cout << "the number of lowercase letters in \"Hello, world!\" is ";
constN<count_lower("Hello, world!")>(); // the string literal is implicitly
// converted to conststr
}
结果
the number of lowercase letters in "Hello, world!" is 9

缺陷报告

以下改变行为的缺陷报告已追溯应用于先前发布的 C++ 标准。

DR应用于发布时的行为正确行为
CWG 1453C++11字面类可以有 volatile 数据成员不允许
CWG 1951C++11 C++14不清楚带有 cv 限定符的 void(C++14)和类类型(C++11)是否是字面类型它们是
CWG 2096C++11对于联合类型要成为字面类型,其所有非静态数据成员都必须是字面类型只需要一个非静态数据成员
CWG 2598C++11对于联合类型要成为字面类型,它必须至少有一个非静态数据成员它可以没有非静态数据成员