Difference between revisions of "cpp/language/variable template"
m (link template template args) |
m (-' ') |
||
(19 intermediate revisions by 14 users not shown) | |||
Line 1: | Line 1: | ||
− | {{title|Variable template}} | + | {{title|Variable template {{mark since c++14}}}} |
− | {{cpp/language/templates/navbar}} | + | {{cpp/language/declarations/expressions/templates/navbar}} |
A variable template defines a family of variables or static data members. | A variable template defines a family of variables or static data members. | ||
Line 6: | Line 6: | ||
===Syntax=== | ===Syntax=== | ||
{{sdsc begin}} | {{sdsc begin}} | ||
− | {{sdsc|{{ttb|template}} {{ttb|<}} {{spar|parameter-list}} {{ttb|>}} {{spar|variable-declaration}} }} | + | {{sdsc|num=1|{{ttb|template}} {{ttb|<}} {{spar|parameter-list}} {{ttb|>}} {{spar|variable-declaration}}}} |
+ | {{sdsc|num=2|notes={{mark since c++20}}|{{ttb|template}} {{ttb|<}} {{spar|parameter-list}} {{ttb|>}} {{ttb|requires}} {{spar|constraint}} {{spar|variable-declaration}}}} | ||
{{sdsc end}} | {{sdsc end}} | ||
− | |||
{{par begin}} | {{par begin}} | ||
− | {{par | {{spar|variable-declaration}} | a {{rlp|declarations|declaration}} of | + | {{par|{{spar|variable-declaration}}|a {{rlp|declarations|declaration}} of a variable. The declared variable name becomes a template name.}} |
− | {{par | {{spar|parameter-list}} | a non-empty comma-separated list of the {{rlp|template parameters}}, each of which is either | + | {{par|{{spar|parameter-list}}|a non-empty comma-separated list of the {{rlp|template parameters}}, each of which is either {{rlp|template parameters#Non-type template parameter|non-type parameter}}, a {{rlp|template parameters#Type template parameter|type parameter}}, a {{rlp|template parameters#Template template parameter|template parameter}}, or a {{rlp|parameter pack}} of any of those.}} |
+ | {{par|{{spar|constraint}}|a {{rlp|constraints|constraint expression}} which restricts the template parameters accepted by this variable template}} | ||
{{par end}} | {{par end}} | ||
− | A variable template may be introduced by a template declaration at namespace scope, where {{spar|declaration}} declares a variable. | + | ===Explanation=== |
+ | A variable instantiated from a variable template is called an ''instantiated variable''. A static data member instantiated from a static data member template is called an ''instantiated static data member''. | ||
+ | |||
+ | A variable template may be introduced by a template declaration at namespace scope, where {{spar|variable-declaration}} declares a variable. | ||
{{source|1= | {{source|1= | ||
template<class T> | template<class T> | ||
− | constexpr T pi = T(3. | + | constexpr T pi = T(3.1415926535897932385L); // variable template |
template<class T> | template<class T> | ||
Line 31: | Line 35: | ||
{{source|1= | {{source|1= | ||
+ | using namespace std::literals; | ||
struct matrix_constants | struct matrix_constants | ||
{ | { | ||
Line 37: | Line 42: | ||
template<class T> // static data member template | template<class T> // static data member template | ||
− | static constexpr pauli<T> | + | static constexpr pauli<T> sigmaX = {<!---->{0, 1}, {1, 0}<!---->}; |
template<class T> | template<class T> | ||
− | static constexpr pauli<T> | + | static constexpr pauli<T> sigmaY = {<!---->{0, -1i}, {1i, 0}<!---->}; |
template<class T> | template<class T> | ||
− | static constexpr pauli<T> | + | static constexpr pauli<T> sigmaZ = {<!---->{1, 0}, {0, -1}<!---->}; |
}; | }; | ||
}} | }} | ||
Line 50: | Line 55: | ||
{{source|1= | {{source|1= | ||
− | struct limits { | + | struct limits |
+ | { | ||
template<typename T> | template<typename T> | ||
static const T min; // declaration of a static data member template | static const T min; // declaration of a static data member template | ||
}; | }; | ||
+ | |||
template<typename T> | template<typename T> | ||
const T limits::min = { }; // definition of a static data member template | const T limits::min = { }; // definition of a static data member template | ||
template<class T> | template<class T> | ||
− | class X { | + | class X |
− | + | { | |
+ | static T s; // declaration of a non-template static data member of a class template | ||
}; | }; | ||
+ | |||
template<class T> | template<class T> | ||
T X<T>::s = 0; // definition of a non-template data member of a class template | T X<T>::s = 0; // definition of a non-template data member of a class template | ||
}} | }} | ||
− | Unless a variable template was {{rlp|template specialization|explicitly specialized}} or explicitly instantiated, it is implicitly instantiated when a specialization of the variable template is used. | + | Unless a variable template was {{rlp|template specialization|explicitly specialized}} or explicitly instantiated, it is implicitly instantiated when a specialization of the variable template is referenced in a context that requires {{rlp|definition#ODR-use|a variable definition to exist}} <!-- P0859R0 -->or if the existence of the definition affects the semantics of the program, i.e. if the variable is {{rlp|constant expression#Functions and variables needed for constant evaluation|needed for constant evaluation}} by an expression (the definition may be not used). |
− | + | The existence of a definition of a variable is considered to affect the semantics of the program if the variable is needed for constant evaluation by an expression, even if constant evaluation of the expression is not required or if constant expression evaluation does not use the definition. | |
===Notes=== | ===Notes=== | ||
Until variable templates were introduced in C++14, parametrized variables were typically implemented as either static data members of class templates or as constexpr function templates returning the desired values. | Until variable templates were introduced in C++14, parametrized variables were typically implemented as either static data members of class templates or as constexpr function templates returning the desired values. | ||
− | Variable templates cannot be used as {{ | + | Variable templates cannot be used as {{rlpsd|template parameters#Template template arguments}}. |
+ | {{feature test macro|__cpp_variable_templates|Variable templates|value=201304L|std=C++14}} | ||
+ | |||
+ | ===Defect reports=== | ||
+ | {{dr list begin}} | ||
+ | {{dr list item|wg=cwg|dr=2255|std=C++14|before=it was unclear whether a specialization of a static<br>data member template is a static data member|after=it is}} | ||
+ | {{dr list end}} | ||
+ | |||
+ | {{langlinks|es|ja|ru|zh}} |
Latest revision as of 01:44, 8 July 2024
A variable template defines a family of variables or static data members.
Contents |
[edit] Syntax
template < parameter-list > variable-declaration
|
(1) | ||||||||
template < parameter-list > requires constraint variable-declaration
|
(2) | (since C++20) | |||||||
variable-declaration | - | a declaration of a variable. The declared variable name becomes a template name. |
parameter-list | - | a non-empty comma-separated list of the template parameters, each of which is either non-type parameter, a type parameter, a template parameter, or a parameter pack of any of those. |
constraint | - | a constraint expression which restricts the template parameters accepted by this variable template |
[edit] Explanation
A variable instantiated from a variable template is called an instantiated variable. A static data member instantiated from a static data member template is called an instantiated static data member.
A variable template may be introduced by a template declaration at namespace scope, where variable-declaration declares a variable.
template<class T> constexpr T pi = T(3.1415926535897932385L); // variable template template<class T> T circular_area(T r) // function template { return pi<T> * r * r; // pi<T> is a variable template instantiation }
When used at class scope, variable template declares a static data member template.
using namespace std::literals; struct matrix_constants { template<class T> using pauli = hermitian_matrix<T, 2>; // alias template template<class T> // static data member template static constexpr pauli<T> sigmaX = {{0, 1}, {1, 0}}; template<class T> static constexpr pauli<T> sigmaY = {{0, -1i}, {1i, 0}}; template<class T> static constexpr pauli<T> sigmaZ = {{1, 0}, {0, -1}}; };
As with other static members, a definition of a static data member template may be required. Such definition is provided outside the class definition. A template declaration of a static data member at namespace scope may also be a definition of a non-template data member of a class template:
struct limits { template<typename T> static const T min; // declaration of a static data member template }; template<typename T> const T limits::min = { }; // definition of a static data member template template<class T> class X { static T s; // declaration of a non-template static data member of a class template }; template<class T> T X<T>::s = 0; // definition of a non-template data member of a class template
Unless a variable template was explicitly specialized or explicitly instantiated, it is implicitly instantiated when a specialization of the variable template is referenced in a context that requires a variable definition to exist or if the existence of the definition affects the semantics of the program, i.e. if the variable is needed for constant evaluation by an expression (the definition may be not used).
The existence of a definition of a variable is considered to affect the semantics of the program if the variable is needed for constant evaluation by an expression, even if constant evaluation of the expression is not required or if constant expression evaluation does not use the definition.
[edit] Notes
Until variable templates were introduced in C++14, parametrized variables were typically implemented as either static data members of class templates or as constexpr function templates returning the desired values.
Variable templates cannot be used as template template arguments.
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_variable_templates |
201304L | (C++14) | Variable templates |
[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 2255 | C++14 | it was unclear whether a specialization of a static data member template is a static data member |
it is |