Variadic templates in VC++ 2013

The VC++ 2013 compiler supports variadic templates. They are templates that can take a variable number of template arguments. In my opinion, it’s more a feature for library authors than for library consumers, so I am not sure how popular its use will be among end-user C++ developers. Here’s a very simple example that shows variadic templates in action.

// Variadic template declaration
template<typename... Args> class Test;

// Specialization 1
template<typename T> class Test<T>
{
public:
  T Data;
};

// Specialization 2
template<typename T1, typename T2> class Test<T1, T2>
{
public:
  T1 Left;
  T2 Right;
};

void Foo()
{
  Test<int> data;
  data.Data = 24;

  Test<int, int> twovalues;
  twovalues.Left = 12;
  twovalues.Right = 15;
}

The intellisense kicks in and works beautifully too when using variadic templates. I will be trying to blog more on the use of variadic templates in the near future.

Difference between std::move and std::forward

In really simple terms, std::move returns an argument as an rvalue reference while std::forward returns either an lvalue reference or an rvalue reference based on how the argument was passed in to the current function. While this is fairly obvious once you get the hang of it, it can be quite tricky to grasp earlier on. The easiest way to see how they work differently is to try some code such as the following:

void Show(int&&)
{
	cout << "int&& called" << endl;
}

void Show(int&)
{
	cout << "int& called" << endl;
}

template<typename T> void Foo(T&& x)
{
	cout << "straight: ";
	Show(x);

	cout << "move: ";
	Show(move(x));
	
	cout << "forward: ";
	Show(forward<T>(x));
	
	cout << endl;
}

int _tmain(void)
{
	Foo(10);

	int x=10;
	Foo(x);
	return 0;
}

The output of the above code is:

straight: int& called
move: int&& called
forward: int&& called

straight: int& called
move: int&& called
forward: int& called

When Foo is called with an rvalue, T&& is deduced as int&&. But the variable itself is an lvalue within that function. So the straight call calls the Show(int&) overload – no surprises there. Both the move-call and the forward-call calls Show(int&&) as expected. In the 2nd case, Foo is called with an lvalue, and again the straight call will go to Show(int&) while the move-call will go to Show(int&&). Now here’s where forward comes in handy, it will go to Show(int&) because that’s what T has been deduced to in this instance of the function call (perfect forwarding). If you are wondering why, the collapsing rule for T&& collapses it to T& during template argument type deduction.