Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Literal Type Class in C++11/C++14

int x = 1; // Not Constant

class A {
    public:
        int value  = x;
        int value2 { x };
        A( int a )        : value( x ), value2( x ) {}
        A( int a, int b ) : value{ x }, value2{ x } {}
        constexpr A() : value{ 0 }, value2{ 0 } {}
};

constexpr int function( A obj1, A obj2, A obj3, A obj4, A obj5, A obj6, A obj7 ){ 
    return 1; 
}

int main(){

    int y = 2; // Not Constant
    A obj1   ( y );
    A obj2   { y };
    A obj3 =   y  ;
    A obj4 = { y };
    A obj5   ( y, y );
    A obj6   { y, y );
    A obj7 = { y, y };
    int var = function( obj1, obj2, obj3, obj4, obj5, obj6, obj7 );

    return 0;
}

C++11 Standard (ISO/IEC 14882:2011), Section 3.9, Paragraph 10 states (emphasis mine):

A type is a literal type if it is:

  • a scalar type; or
  • a reference 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
    • it has all non-static data members and base classes of literal types; or
  • an array of literal type.

In my opinion, taking into account the bullet in bold, class A is not a literal type in C++11 because there are constructor calls and a brace-or-equal-initializers for non-static data members that are not constant expressions. I tried putting constexpr before the constructor definition and also assigning the constructor call to a constexpr variable to check that indeed the compiler complains because those are not constant expressions. However, both Clang and GCC compile it successfully. So I am probably wrong.

  • Does anyone know why class A is a literal type?

The bullet in bold was removed in C++14 (N3652), so I understand class A is a literal type in C++14. I need to know because function is constexpr, therefore each of its parameter types shall be a literal type (C++11/C++14 Standard, Section 7.1.15, Paragraph 3).

EDIT: In the Original Post I used a simple example to make it easier to read, and explained I already tried many combinations. Now I updated the example with some of those combinations to show I tried different constructor calls, definitions and non-static data member initializations. Thanks.

like image 754
J L Avatar asked Feb 02 '17 13:02

J L


People also ask

What is a literal type in C++?

A literal class type is a class type that has a trivial destructor, is either an aggregate type or has at least one non-move, non-copy constexpr constructor, and all of its base classes and non-static data members are non-volatile literal types.

What is literal type in TypeScript?

The string literal type allows you to specify a set of possible string values for a variable, only those string values can be assigned to a variable. TypeScript throws a compile-time error if one tries to assign a value to the variable that isn't defined by the string literal type.

What is meant by literals how many types of integer literals are available in C++?

Generally, both terms, constants, and literals are used interchangeably. For example, “const int = 5;“, is a constant expression and the value 5 is referred to as a constant integer literal. There are 4 types of literal in C and five types of literal in C++.


1 Answers

Does anyone know why class A is a literal type?

It's not in C++11, but it is in C++14, for the reasons you cite in your post. However...

However, both Clang and GCC compile it successfully. So I am probably wrong.

You are not wrong. Neither are clang and gcc. The code is, indeed, well-formed despite A not being a literal type... simply because nothing requires it to be a literal type. function may be a constexpr function, but it isn't being invoked as a constant expression. var isn't a constexpr object, so there's no enforced requirement that all the objects be of literal type. Had you tried:

constexpr int var = function(...);

then the code would be ill-formed, as in this case, function(...) would need to be a core constant expression, which requires literal types, which is a requirement that in C++11 A failed. (Actually, you'd also have the problem in C++14 that none of the As are constexpr objects).

like image 145
Barry Avatar answered Sep 19 '22 14:09

Barry