Namespaces
Variants

C++ named requirements: LiteralType (since C++11)

From cppreference.net
C++ named requirements

指定某个类型为 字面类型 。字面类型是 constexpr 变量 的类型,并且可以从 constexpr 函数 中构造、操作和返回这些类型。

注意:标准并未定义以此命名的具名要求。这是由核心语言定义的类型类别。此处将其作为具名要求收录仅为保持一致性。

目录

要求

字面类型是以下任意一种:

  • 可能带有 cv 限定符的 void (使得 constexpr 函数可以返回 void);
(since C++14)
  • 拥有 平凡 (C++20 前) constexpr (C++20 起) 析构函数
  • 其所有非静态非变体数据成员和基类均为非易失性字面类型,且
  • 满足以下条件之一
(since C++17)
  • 不包含 变体成员 ,或
  • 至少拥有一个非易失性字面类型的变体成员,
  • 不包含 变体成员 ,或
  • 至少拥有一个非易失性字面类型的变体成员,
  • 具有至少一个非拷贝/移动构造函数的 constexpr (可能是模板)构造函数的类型。

注释

即使某个类型的所有constexpr构造函数都被删除、不可访问或无法参与重载决议,该类型仍可能是字面类型。

struct A { constexpr A(int) = delete; char c; }; // A 是字面类型
constexpr A v = std::bit_cast<A>('0'); // C++20 中合法
                                       // v 具有字面类型,因此可以是 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++标准。

缺陷报告 应用于 发布时的行为 正确行为
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 中移除)
检查类型是否为字面类型
(类模板)