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

Number of atoms in 2 moles=1.2046e+24
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

90
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
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.