27

The book I'm reading frequently mentions that a type has to be literal type to use in certain situations, such as types that can use constexpr. But the only definition given was that literal types are arithmetic, reference, or pointer types. But when we define a constexpr type, it seems like it has to be initialized with a literal or a variable that was originally initialized with a literal.

I'm confused with what qualifies as a literal type and what doesn't.

Mars
  • 4,677
  • 8
  • 43
  • 65

2 Answers2

22

From C++11, 3.9/10:

A type is a literal type if it is:

  • a scalar type; or
  • a reference type; or
  • an array of literal type; or
  • a class type (Clause 9) that has all of the following properties:
    • it has a trivial destructor,
    • every constructor call and full-expression in the brace-or-equal-initializers for non-static data members (if any) is a constant expression (5.19),
    • it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
    • all of its non-static data members and base classes are of literal types.

So basically it's either a reference, or a primitive object type, or something that can be constructed from a literal type in a constexpr-sort of way (arrays, aggregates, or classes with constexpr constructor).

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 5
    What is an example of a non literal type? – Mars Sep 02 '13 at 22:23
  • 2
    @Comrade: `std::string`. – Kerrek SB Sep 02 '13 at 22:23
  • 2
    So most generally non literal types are class types excluding the special class types included above in the answer. – Mars Sep 02 '13 at 22:28
  • 6
    @Comrade: Yes. Basically any non-trivial construction logic (especially dynamic memory allocation) makes your type non-literal. If you will, the state of the object cannot just be expressed by something you write down; it also depends on the dynamic history of the object. – Kerrek SB Sep 02 '13 at 22:30
  • @KerrekSB I wonder if the second requirement for class types isn't actually redundant. According to the third, it's either an aggregate and has no such initializers, or it has a constexpr ctor, which requires the same as the second. – dyp Sep 02 '13 at 22:40
  • @dyp: Pull from HEAD and rebuild, I think the wording has changed since and you will like it. – Kerrek SB Nov 27 '14 at 10:53
3

C++11 (n3485), [basic.types]9-10

Arithmetic types, enumeration types, pointer types, pointer to member types, std::nullptr_t, and cv-qualified versions of these types are collectively called scalar types [...]

A type is a literal type if it is:

  • a scalar type; or
  • a reference type; or
  • an array of literal type; or
  • a class type that has all of the following properties:
    • it has a trivial destructor,
    • every constructor call and full-expression in the brace-or-equal-initializers for non-static data members (if any) is a constant expression,
    • it is an aggregate type or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
    • all of its non-static data members and base classes are of non-volatile literal types.

[dcl.init.aggr]/1

An aggregate is an array or a class with no user-provided constructors, no brace-or-equal-initializers for non-static data members, no private or protected non-static data members, no base classes, and no virtual functions.

dyp
  • 38,334
  • 13
  • 112
  • 177