Variable templates in C++14

While studying the new C++ standard, I came across the innovation " variable templates"

The syntax of the template is as follows:

template < typename T >
constexpr T value = T(1234);

About the application of the template it is written:

This feature allows you to create and use constexpr variable templates, for a more convenient combination with template algorithms.

I don't quite understand how such a variable will be used in the template algorithm. Could you please bring some examples of using this mechanism? I also don't understand why such a template constexpr expression can't be replaced by with a non-template, because we specify the value explicitly, respectively, and we can write (output) the type explicitly.

Author: Harry, 2017-10-30

2 answers

The standard has example:

template<class T>
constexpr T pi = T(3.1415926535897932385L);

template<class T>
T circular_area(T r) {
  return pi<T> * r * r;
}

Here, the variable template allows you to get a constant of the desired size-float/double/etc.


Another popular use is to replace is_some<T>::value with is_some_v<T>, for example

template< class T, class U >
inline constexpr bool is_same_v = is_same<T, U>::value;  // C++17
 16
Author: Abyx, 2017-10-30 15:40:23

Here you can notice that when declaring a template variable, the type of this variable does not have to match the template parameter at all, or even be somehow related to the template parameter (s). Most trivial examples of variable templates usually give the variable the same type that was used in the template parameter, which can give the false impression that this is required. In fact, a template variable can have any type.

For example, using the example with an area of you can choose to use the "basic" definition of the constant PI with a specific type double

template<class T> constexpr double PI = 3.141592653589793;

And then, using explicit specialization, add specialized definitions for individual floating types

template<> constexpr float PI<float> = 3.1415927;
template<> constexpr long double PI<long double> = 3.141592653589793238L;

After that, it will be possible to implement a "single" template function for calculating the area of the circle

template<class T> T circle_area(T r) 
{
  return PI<T> * r * r;
}

Which will, for example, work with integer types

int area = circle_area(10);

For integer types as the PI constant will take the "default" option with the double type, and for floating types, the specialized values of this constant will be used.

The implementation of this function from @Abyx's answer, as you probably noticed, will also "work" with integer types. But in that variant, the Pi constant for integer types will get the integer value 3, which is not always desirable.


You can also add that the ability to enable static data members in class templates have existed in C++ since the beginning of standardized times, i.e. in C++98. This made it possible to implement "variable templates" even then, using virtually the same technique that was used in C++98 for "template typedef" , i.e. by placing types or variables in the" wrapper " of a template class. In particular, the above example can be implemented in classical C++98 as

template <typename T> struct PI { static const double value; };
template <typename T> const double PI<T>::value = 3.141592653589793;

template <> struct PI<float> { static const float value; };
const float PI<float>::value = 3.1415927;

template <> struct PI<long double> { static const long double value; };
const long double PI<long double>::value = 3.141592653589793238L;

template<class T> T circle_area(T r) 
{
  return PI<T>::value * r * r;
}

Taking this into account, you can to say that template variables are not some fundamentally new property of C++14. They are (loosely speaking) just "syntactic sugar", a more compact and elegant version of the syntax for writing the above C++98 implementation. The situation is similar to the ability introduced in C++11 to declare template typedef (via using), which can also be called "syntactic sugar" over the well-known C++98 technique of "template typedef".

 6
Author: AnT, 2017-11-01 00:56:03