C++ named requirements: LiteralType

< cpp‎ | named req
C++ named requirements
Type properties
Container Elements
Stream I/O
Random Numbers

Specifies that a type is a literal type. Literal types are the types of constexpr variables and they can be constructed, manipulated, and returned from constexpr functions.

Note: the standard doesn't define a named requirement with this name. This is a type category defined by the core language. It is included here as a named requirement only for consistency.


[edit] Requirements

A literal type is any of the following:

  • possibly cv-qualified void (so that constexpr functions can return void);
(since C++14)
  • scalar type;
  • reference type;
  • an array of literal type;
  • possibly cv-qualified class type that has all of the following properties:
  • has a trivial (until C++20)constexpr (since C++20) destructor,
  • is one of
  • an aggregate type,
  • a type with at least one constexpr (possibly template) constructor that is not a copy or move constructor,
(since C++17)
  • for unions, at least one non-static data member is of non-volatile literal type,
  • for non-unions, all non-static data members and base classes are of non-volatile literal types.

[edit] Notes

A type can be literal even if all of its constexpr constructors are deleted, inaccessible, or cannot participate in overload resolution.

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

[edit] Example

Literal type that extends string literals:

#include <iostream>
#include <stdexcept>
class conststr
    const char* p;
    std::size_t sz;
    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 countlower(conststr s, std::size_t n = 0,
                                             std::size_t c = 0)
    return n == s.size() ? c :
           s[n] >= 'a' && s[n] <= 'z' ? countlower(s, n + 1, c + 1) :
                                        countlower(s, n + 1, c);
// output function that requires a compile-time constant, 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<countlower("Hello, world!")>(); // implicitly converted to conststr


the number of lowercase letters in "Hello, world!" is 9

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
CWG 1951 C++11 (class type)
C++14 (void)
unclear if cv-qualified void and class types are literal types they are
CWG 2096 C++11 for a union type to be literal, all its non-static data members must be literal only one non-static data member needs to be

[edit] See also

(C++11)(deprecated in C++17)(removed in C++20)
checks if a type is a literal type
(class template) [edit]