C++14#Relaxed constexpr restrictions
{{Short description|2014 edition of the C++ programming language standard}}
{{C++ language revisions}}
C++14 is a version of the ISO/IEC 14882 standard for the C++ programming language. It is intended to be a small extension over C++11, featuring mainly bug fixes and small improvements, and was replaced by C++17. Its approval was announced on August 18, 2014.{{Citation |title=We have C++14! |first=Herb |last=Sutter |date=August 18, 2014 |url=https://isocpp.org/blog/2014/08/we-have-cpp14 |access-date=2014-08-18}} C++14 was published as ISO/IEC 14882:2014 in December 2014.{{Cite web|url=https://www.iso.org/cms/render/live/en/sites/isoorg/contents/data/standard/06/40/64029.html|title=ISO/IEC 14882:2014|website=ISO}}
Because earlier C++ standard revisions were noticeably late, the name "C++1y" was sometimes used instead until its approval, similarly to how the C++11 standard used to be termed "C++0x" with the expectation of its release before 2010 (although in fact it slipped into 2010 and finally 2011).
New language features
These are the features added to the core language of C++14.
= Function return type deduction =
C++11 allowed lambda functions to deduce the return type based on the type of the expression given to the return statement. C++14 provides this ability to all functions. It also extends these facilities to lambda functions, allowing return type deduction for functions that are not of the form return expression;
.{{cite web|last = Wong|first = Michael|title = The View from the C++ Standard meeting April 2013 Part 1|url = https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/the_view_from_c_standard_meeting_april_2013_part_1?lang=en|work = C/C++ Cafe|date = 30 April 2013|access-date = 27 January 2016}}
In order to induce return type deduction, the function must be declared with auto
as the return type, but without the trailing return type specifier in C++11:
auto DeduceReturnType(); // Return type to be determined.
If multiple return expressions are used in the function's implementation, then they must all deduce the same type.{{cite web|title=N3638 Return type deduction for normal functions (Revision 5)|url=http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3638.html|last=Merrill|first=Jason|date=17 April 2013|access-date=14 June 2013}}
Functions that deduce their return types can be forward declared, but they cannot be used until they have been defined. Their definitions must be available to the translation unit that uses them.
Recursion can be used with a function of this type, but the recursive call must happen after at least one return statement in the definition of the function:
auto Correct(int i)
{
if (i == 1)
return i; // return type deduced as int
return Correct(i-1)+i; // ok to call it now
}
auto Wrong(int i)
{
if (i != 1)
return Wrong(i-1)+i; // Too soon to call this. No prior return statement.
return i; // return type deduced as int
}
= Alternate type deduction on declaration =
In C++11, two methods of type deduction were added. auto
was a way to create a variable of the appropriate type, based on a given expression. decltype
was a way to compute the type of a given expression. However, decltype
and auto
deduce types in different ways. In particular, auto
always deduces a non-reference type, as though by using std::decay
, while auto&&
always deduces a reference type. However, decltype
can be prodded into deducing a reference or non-reference type, based on the value category of the expression and the nature of the expression it is deducing:{{Cite web|url=http://thbecker.net/articles/auto_and_decltype/section_10.html|title = Page 10 of: C++ auto and decltype Explained}}
int i;
int&& f();
auto x3a = i; // decltype(x3a) is int
decltype(i) x3d = i; // decltype(x3d) is int
auto x4a = (i); // decltype(x4a) is int
decltype((i)) x4d = (i); // decltype(x4d) is int&
auto x5a = f(); // decltype(x5a) is int
decltype(f()) x5d = f(); // decltype(x5d) is int&&
C++14 adds the decltype(auto)
syntax. This allows auto
declarations to use the decltype
rules on the given expression.
The decltype(auto)
syntax can also be used with return type deduction, by using decltype(auto)
syntax instead of auto
for the function's return type deduction.
= Relaxed constexpr restrictions =
C++11 introduced the concept of a constexpr-declared function; a function which could be executed at compile time. Their return values could be consumed by operations that require constant expressions, such as an integer template argument. However, C++11 constexpr functions could only contain a single expression that is returned (as well as static_assert
s and a small number of other declarations).
C++14 relaxes these restrictions. Constexpr-declared functions may now contain the following:
- Any declarations except:
static
orthread_local
variables.- Variable declarations without initializers.
- The conditional branching statements
if
andswitch
. - Any looping statement, including range-based
for
. - Expressions which change the value of an object if the lifetime of that object began within the constant expression function. This includes calls to any non-
const
constexpr
-declared non-static member functions.
goto
statements are forbidden in C++14 relaxed constexpr-declared functions.
Also, C++11 stated that all non-static member functions that were declared constexpr
were also implicitly declared const
, with respect to this
. That has since been removed; non-static member functions may be non-const
.{{cite web|title=N3652 Relaxing constraints on constexpr functions|first=Richard|last=Smith|date=18 April 2013|url=http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3652.html}} However, per the restrictions above, a non-const
constexpr
member function can only modify a class member if that object's lifetime began within the constant expression evaluation.
= Variable templates =
In prior versions of C++, only functions, classes or type aliases could be templated. C++14 allows the creation of variables that are templated. An example given in the proposal is a variable pi
that can be read to get the value of pi for various types (e.g., 3
when read as an integral type; the closest value possible with float
, double
or long double
precision when read as float
, double
or long double
, respectively; etc.).
The usual rules of templates apply to such declarations and definitions, including specialization.{{cite web|title=N3651 Variable Templates (Revision 1)|url=http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3651.pdf|last=Dos Reis|first=Gabriel|date=19 April 2013}}
template
constexpr T pi = T(3.141592653589793238462643383);
// Usual specialization rules apply:
template<>
constexpr const char* pi
= Aggregate member initialization =
C++11 added default member initializers, expressions to be applied to members at class scope if a constructor did not initialize the member itself. The definition of aggregates was changed to explicitly exclude any class with member initializers; therefore, they are not allowed to use aggregate initialization.
C++14 relaxes this restriction, allowing aggregate initialization on such types. If the braced init list does not provide a value for that argument, the member initializer takes care of it.{{cite web|title=N3653 Member initializers and aggregates|url=http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3653.html|date=17 April 2013|first1=Daveed|last1=Vandevoorde|first2=Ville|last2=Voutilainen}}
= Binary literals =
Numeric literals in C++14 can be specified in binary form. The syntax uses the prefixes 0b
or 0B
. The syntax is also used in other languages e.g. Java, C#, Swift, Go, Scala, Ruby, Python, OCaml, and as an unofficial extension in some C compilers since at least 2007.{{Cite web|url=https://gcc.gnu.org/bugzilla/show_bug.cgi?id=23479#c29|title = 23479 – Implement binary constants with a "0b" prefix}}
= Digit separators =
In C++14, the single-quote character may be used arbitrarily as a digit separator in numeric literals, both integer literals and floating point literals.{{cite web|title=N3781 Single-Quotation-Mark as a Digit Separator|url=http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf |date=25 September 2013 |first1=Lawrence|last1=Crowl|first2=Richard|last2=Smith|first3=Jeff|last3=Snyder|first4=Daveed|last4=Vandevoorde}} This can make it easier for human readers to parse large numbers through subitizing.
auto integer_literal = 1'000'000;
auto floating_point_literal = 0.000'015'3;
auto binary_literal = 0b0100'1100'0110;
auto a_dozen_crores = 12'00'00'000;
= Generic lambdas =
In C++11, lambda function parameters need to be declared with concrete types. C++14 relaxes this requirement, allowing lambda function parameters to be declared with the auto
type specifier.{{cite web|last=Sutter|first=Herb|author-link=Herb Sutter|title=Trip Report: ISO C++ Spring 2013 Meeting|url=http://isocpp.org/blog/2013/04/trip-report-iso-c-spring-2013-meeting|date=20 April 2013|website=isocpp.org|access-date=14 June 2013}}
auto lambda = [](auto x, auto y) {return x + y;};
Concerning auto
type deduction, generic lambdas follow the rules of template argument deduction (which are similar, but not identical in all respects{{Clarify|reason=Similar to what? Either it follows the rules for template type deduction or it doesn't. Do we mean "it follows rules similar to those for template type deduction?"|date=October 2019}}). The code above is equivalent to this:{{cite web|title=N3649 Generic (Polymorphic) Lambda Expressions (Revision 3)|first1=Faisal|last1=Vali|first2=Herb|last2=Sutter|first3=Dave|last3=Abrahams|date=19 April 2013|url=http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3649.html}}
struct
{
template
auto operator()(T x, U y) const {return x + y;}
} lambda{};
Generic lambdas are essentially templated functor lambdas.
= Lambda capture expressions =
C++11 lambda functions capture variables declared in their outer scope by value-copy or by reference. This means that value members of a lambda cannot be move-only types.{{cite web|title=Move capture in Lambda|url=https://stackoverflow.com/questions/8640393/move-capture-in-lambda|website=Stack Overflow}} C++14 allows captured members to be initialized with arbitrary expressions. This allows both capture by value-move and declaring arbitrary members of the lambda, without having a correspondingly named variable in an outer scope.
This is done via the use of an initializer expression:
auto lambda = [value = 1] {return value;};
The lambda function lambda
returns 1, which is what value
was initialized with. The declared capture deduces the type from the initializer expression as if by auto
.
This can be used to capture by move, via the use of the standard std::move
function:
std::unique_ptr
auto lambda = [value = std::move(ptr)] {return *value;};
=The attribute <code><nowiki>[[deprecated]]</nowiki></code>=
The deprecated
attribute allows marking an entity deprecated, which makes it still legal to use but puts users on notice that use is discouraged and may cause a warning message to be printed during compilation. An optional string literal can appear as the argument of deprecated
, to explain the rationale for deprecation and suggest a replacement.
deprecated int f();
deprecated("g() is thread-unsafe. Use h() instead")
void g( int& x );
void h( int& x );
void test()
{
int a = f(); // warning: 'f' is deprecated
g(a); // warning: 'g' is deprecated: g() is thread-unsafe. Use h() instead
}
New standard library features
= Shared mutexes and locking =
C++14 adds a shared timed mutex and a companion shared lock type.{{cite web|last=Wong|first=Michael|title=The View from the C++ Standard meeting April 2013 Part 3|url=https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/the_view_form_the_c_standard_meeting_april_2013_part_3?lang=en|work=C/C++ Cafe|access-date=14 June 2013|date=30 April 2013}}{{cite web|title=N3659 Shared locking in C++ (Revision 2)|url=http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3659.html|date=19 April 2013|first1=Howard|last1=Hinnant|first2=Detlef|last2=Vollmann|first3=Hans|last3=Boehm}}
= Heterogeneous lookup in associative containers =
The C++ Standard Library defines four associative container classes. These classes allow the user to look up a value based on a value of that type. The map containers allow the user to specify a key and a value, where lookup is done by key and returns a value. However, the lookup is always done by the specific key type, whether it is the key as in maps or the value itself as in sets.
C++14 allows the lookup to be done via an arbitrary type, so long as the comparison operator can compare that type with the actual key type.{{cite web|last=Wong|first=Michael|title=The View from the C++ Standard meeting April 2013 Part 2|url=https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/the_view_form_the_c_standrd_meeting_april_2013_part_2?lang=en|work=C/C++ Cafe|date=26 April 2013|access-date=14 June 2013}} This would allow a map from std::string
to some value to compare against a const char*
or any other type for which an operator<
overload is available. It is also useful for indexing composite objects in a std::set
by the value of a single member without forcing the user of find
to create a dummy object (for example creating an entire struct Person
to find a person by name).
To preserve backwards compatibility, heterogeneous lookup is only allowed when the comparator given to the associative container allows it. The standard library classes std::less<>
and std::greater<>
are augmented to allow heterogeneous lookup.{{cite web|title=N3657 Adding heterogeneous comparison lookup to associative containers (rev 4)|date=19 March 2013|url=http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3657.htm}}
= Standard user-defined literals =
C++11 defined the syntax for user-defined literal suffixes, but the standard library did not use any of them. C++14 adds the following standard literals:
- "s", for creating the various
std::basic_string
types. - "h", "min", "s", "ms", "us", "ns", for creating the corresponding
std::chrono::duration
time intervals. - "if", "i", "il", for creating the corresponding
std::complex
,std::complex
andstd::complex
imaginary numbers.
auto str = "hello world"s; // auto deduces string
auto dur = 60s; // auto deduces chrono::seconds
auto z = 1i; // auto deduces complex
The two "s" literals do not clash, as the string one only operates on string literals, and the one for seconds operates only on numbers.{{cite web|title=N3642 User-defined Literals for Standard Library Types (part 1 - version 4)|first=Peter|last=Sommerlad|date=18 April 2013|url=http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3642.pdf}}
= Tuple addressing via type =
The std::tuple
type introduced in C++11 allows an aggregate of typed values to be indexed by a compile-time constant integer. C++14 extends this to allow fetching from a tuple by type instead of by index. If the tuple has more than one element of the type, a compile-time error results:{{cite web|title=N3670 Wording for Addressing Tuples by Type: Revision 2|date=19 April 2013|last=Spertus|first=Mike|url=http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3670.html}}
tuple
int i = get
int j = get<2>(t); // Same as before: j == 7
string s = get
= Smaller library features =
std::make_unique
can be used like std::make_shared
for std::unique_ptr
objects.
std::integral_constant
gained an operator()
overload to return the constant value.
The class template std::integer_sequence
and related alias templates were added for representing compile-time integer sequences, such as the indices of elements in a parameter pack.{{cite web | title=N3658 Compile-time integer sequences | url=http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3658.html |last=Wakely|first=Jonathan|date=18 April 2013|access-date=5 January 2016}}
The global std::begin
/std::end
functions were augmented with std::cbegin
/std::cend
functions, which return constant iterators, and std::rbegin
/std::rend
and std::crbegin
/std::crend
which return reverse iterators.
The std::exchange
function template assigns a new value to a variable and returns the old value.{{cite web | title=N3668 exchange() utility function, revision 3 | url=http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3668.html |first=Jeffrey|last=Yasskin|date=19 April 2013|access-date=5 January 2016}}
New overloads of std::equal
, std::mismatch
, and std::is_permutation
take a pair of iterators for the second range, so that the caller does not need to separately check that the two ranges are of the same length.{{cite web | title=N3671 Making non-modifying sequence operations more robust: Revision 2 | url=http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3671.html |last1=Spertus|first1=Mike|last2=Pall|first2=Attila|date=19 April 2013|access-date=5 January 2016}}
The std::is_final
type trait detects if a class is marked final
.
The std::quoted
stream I/O manipulator allows inserting and extracting strings with embedded spaces, by placing delimiters (defaulting to double-quotes) on output and stripping them on input, and escaping any embedded delimiters.{{cite web | title=N3654 Quoted Strings Library Proposal (Revision 2) | url=http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3654.html |last=Dawes|first=Beman|date=19 April 2013|access-date=5 January 2016}}
Compiler support
Clang finished support for C++14 in 3.4 though under the standard name c++1y, and made C++14 the default C++ standard in Clang 6.{{cite web|title=C++ Support in Clang|url=http://clang.llvm.org/cxx_status.html|access-date=28 May 2016}} GCC finished support for C++14 in GCC 5, and made C++14 the default C++ standard in GCC 6.{{cite web|title=C++ Standards Support in GCC|url=https://gcc.gnu.org/projects/cxx-status.html|access-date=28 May 2016}} Microsoft Visual Studio 2017 has implemented "almost all" C++14 features.{{cite web|url=https://blogs.msdn.microsoft.com/vcblog/2017/03/07/c-standards-conformance-from-microsoft/|title=C++ Standards Conformance from Microsoft|date=7 March 2017|access-date=7 March 2017}}
References
{{reflist|30em}}
External links
- [https://web.archive.org/web/20150814081653/http://www.drdobbs.com/cpp/the-c14-standard-what-you-need-to-know/240169034 C++14: What you need to know] Overview of features in Dr. Dobb's, 16 Sept. 2014
{{C++ProLang}}
{{ISO standards}}
{{Programming languages}}
Category:Programming language standards
Category:Articles with example C++ code