The constexpr specifier (C++11)
Note: IBM supports selected
features of C++11, known as C++0x before its ratification. IBM will
continue to develop and implement the features of this standard. The
implementation of the language level is based on IBM's interpretation
of the standard. Until IBM's implementation of all the C++11 features
is complete, including the support of a new C++11 standard library,
the implementation may change from release to release. IBM makes no
attempt to maintain compatibility, in source, binary, or listings
and other compiler interfaces, with earlier releases of IBM's implementation
of the new C++11 features.
The
C++11 standard introduces a new keyword constexpr as
a declaration specifier. You can apply the constexpr specifier
only to the following contexts:
- The definition of a variable
- The declaration of a function or function template
- The declaration of a static data member
constexpr int i = 1; // OK, definition
constexpr int f1(); // OK, function declaration, but must be defined before use
If you declare a function that is not a constructor
with a constexpr specifier, that function is a constexpr function.
Similarly, if you declare a constructor with a constexpr specifier,
that constructor is a constexpr constructor. Both constexpr functions
and constexpr constructors are implicitly inline.
For example:
struct S {
constexpr S(int i) : mem(i) { } // OK, declaration of a constexpr constructor
private:
int mem;
};
constexpr S s(55); // OK, invocation of a constexpr constructor
If any declaration of a function or function template
is specified with constexpr, all its declarations
must contain the constexpr specifier. For example:
constexpr int f1(); // OK, function declaration
int f1() { // Error, the constexpr specifier is missing
return 55;
}
Function parameters cannot be declared with
the constexpr specifier. The following example demonstrates
this:
constexpt int f4(constexpr int); //Error
A constexpr specifier
used in an object declaration declares the object as const.
Such an object must be of a literal type and initialized. If it is
initialized by a constructor call, that call must be a constant expression.
Otherwise, if a constexpr specifier is used in a
reference declaration, every full expression that appears in its initializer
must be a constant expression. Each implicit conversion used in converting
the initializer expressions and each constructor call used for the
initialization must be valid in a constant expression. For example:
constexpr int var; // Error, var is not initialized
constexpr int var1 = 1; // OK
void func() {
var1 = 5; //Error, var1 is const
}
struct L {
constexpr L() : mem(55) { }
constexpr L(double d) : mem((int)d) { }
L(int i) : mem(i) { }
operator int() { return mem; }
private:
int mem;
};
// Error, initializer involves a non-constexpr constructor.
constexpr L var2(55);
double var3 = 55;
// Error, initializer involves a constexpr constructor with non-constant argument
constexpr L var4(var3);
// Error, involves conversion that uses a non-constexpr conversion function
constexpr int var5 = L();
A constexpr specifier
for a nonstatic member function that is not a constructor declares
that member function to be const. The
class of that constexpr member function must be a
literal type. In the following example, the class NL is
a non-literal type because it has a user-provided destructor.
struct NL {
constexpr int f(){ //error, enclosing class is not a literal type
return 55;
}
~NL() { }
};
A call to a constexpr function produces the same result as a call to an equivalent non-constexpr function , except that a call to a constexpr function can appear in a constant expression.
The main function cannot be declared with the constexpr specifier.