C++14 template variable and aggregate member initialization
C++14 added many features and among them, two new features which are C++14 template variable and C++14 aggregate member initialization will be discussed here.
Link :C++14 user-defined literals
C++14 template variable
In C++ we could only make function, class and type alias as template. But C++14 added an extension through which we can also make template variable.
To make a template variable the normal template syntax rule applies. The syntax is shown below.
template<typename T> T var_name= initializer ;
To access the template variable we will write as:
var_name<Type>
The ‘Type‘ is the type of the var_name.
So applying this syntax let’s declare some template variables and try to access the value.
template<class T> constexpr T var=90 ; //a constexpr template variable template<class Ts> Ts st=”String” ; //a normal template variable template<typename Tc> const Tc G=6.67e-11 //a const template variable int main() { //Accessing the template variable cout << st<string> << "\n" << G<const double> << endl ; //note the 'const', it is necessary cout<< var<int> ; //constexpr is not necessary return 0; }
Some rules
If we declare a variable as template then we must declare it outside the scope of any function. This means, we can only have a global scope template variable not local template variable. Declaring a template variable under local scope is an error.
template<typename Tp> Tp val=”String” ; //work fine void func( ) { template<class T> T var=’D’ ; //error! } int main( ) { template<class T> T var=890 ; //error! cin.get( ); return 0 ; }
In Code::Blocks you will most probably get an error message as “template declaration cannot appear at block scope“.
Let’s see a program implementing a template variable.
template< class T> const T avogadro_const = 6.023e23; template< class T> const T str = "template variable" ; template<class T> double number_of_atoms(T mole) //'T' type is deduced from 'mole' type { return avogadro_const<T> * mole; } int main() { double mole = 2; cout << "Number of atoms in " << mole << " moles=" << number_of_atoms(mole) << endl; cout << str<string> ; cin.get(); return 0; }
Output
template variable
C++14 aggregate member initialization
In C++11 we can assign the data member inside the structure. We can also use an aggregate member initializer list to initialize the data members when an object of the structure is declared. Consider the code below.
//Work fine struct A { int i=90; char c=’B’; string st=”String” ; }; //Work fine struct B { int i; char c; string st ; }; int main( ) { A a; cout<< a.i << endl << a.c << endl << a.st ; B b={ 12 , ‘B’ , “Happy” }; //aggregate initialization cout<< a.i << endl << a.c << endl << a.st ; return 0; }
Output
B
String
12
B
Happy
The code above work fine since all the ‘A’ structure members are initialized inside the structure and the B members is initialized using the initializer list.
Suppose, some of the data members are initialized inside the structure and some others not, then we cannot initialize the uninitialized member with the aggregate member initializer list. Here is a code example which shows an instance of such a case. Try to notice the difference.
struct A { int i; char c; string st="All" ; //st is initialized }; int main( ) { A a={12, ‘M’ }; //error! aggregate initialization return 0 ; }
One of the data members of A (st) is initialized inside the structure and also we try to initialize the other uninitialized members using an aggregate initialization list during its object creation. We try to intermingle the two methods of initialization here, which is actually not allowed in C++11.
C++14 however relaxes this restriction. And so if some of the data members are not initialized inside the structure then we can initialize them using the aggregate initialization method. And if there are fewer initializers in the initializer list than the data member is initialized using an empty initializer list.
struct A { int i ; char c ; string st="C++14 exception" ; }; int main( ) { A a={ 12 , ‘A’ }; //work fine cout<< a.i << endl << a.c << endl << a.st << "\n\n" ; A a1={ 90 }; cout<< a1.i << endl << a1.c << endl << a1.st << endl ; cin.get(); return 0; }
Output
12
A
C++14 exception
90
C++14 exception
Note for a1 object the ‘c’ data member is assigned an empty character.
In short, in C++14 we can apply both the methods of initialization in one same structure object which is not allowed in C++11.