Spec-Zone.ru › C++

Именованные требования C++: LiteralType (начиная с C++11)

Указывает, что тип является литеральным типом. Литеральные типы используются для constexpr переменных, а также могут создаваться, изменяться и возвращаться из constexpr-функций.

Примечание: стандарт не определяет именованное требование с таким именем. Это категория типов, определяемая основным языком. Здесь она включена в качестве именованного требования исключительно для единообразия.

Требования

Литеральным типом является любой из следующих типов:

  • возможно, cv-квалифицированный void (чтобы функции constexpr могли возвращать void);
(начиная с C++14)
  • скалярный тип;
  • ссылочный тип;
  • массив литерального типа;
  • возможно, cv-квалифицированный тип класса, обладающий всеми следующими свойствами:
    • имеет тривиальный(до C++20)constexpr(начиная с C++20) деструктор,
    • все его нестатические невариантные члены данных и базовые классы имеют нелетучие литеральные типы, и
    • является одним из следующих типов:
  • тип лямбда-выражения,
(начиная с C++17)
  • тип объединения агрегата, который
    • не имеет вариантных членов или
    • имеет как минимум один вариантный член с нелетучим литеральным типом,
  • не являющийся объединением тип агрегата, каждый из его членов — анонимных объединений
    • не имеет вариантных членов или
    • имеет как минимум один вариантный член с нелетучим литеральным типом,
  • тип, имеющий как минимум один конструктор 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 1453 C++11 литеральный класс мог иметь volatile-члены данных не допускаются
CWG 1951 C++11
C++14
не было ясно, являются ли cv-квалифицированный void (C++14)
и типы классов (C++11) литеральными типами
являются
CWG 2096 C++11 чтобы тип объединения был литеральным, все его
нестатические члены данных должны были быть литеральными
достаточно, чтобы литеральным
был лишь один нестатический член данных
CWG 2598 C++11 чтобы тип объединения был литеральным, он должен был иметь
как минимум один нестатический член данных
он может не иметь
нестатических членов данных

См. также

is_literal_type
(C++11)(устарело в C++17)(удалено в C++20)
проверяет, является ли тип литеральным
(шаблон класса)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/named_req/LiteralType

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API