DanielCollier DanielCollier - 8 days ago 5
C++ Question

How are template arguments expanded

I am confused about the expansion of this template [example one]. If bool b is checked at runtime in the constructor where is b stored ? is it put into the private data section [example two]? or does it become compile time and remove a branched based on the bool? or does it simply "paste" what was passed as a template argument into the if(b) [example 3]

Example one:

template<bool b>
class Test
{
public:
Test()
{
if(b)
{
// do something
}
else
{
// do something else
}
}
};


Example two:

class Test
{
public:
Test()
{
if(b)
{
// do something
}
else
{
// do something else
}
}

private:
bool b = true;
};


Example three:

//called with Test<true>

class Test
{
public:
Test()
{
if(true)
{
// do something
}
else
{
// do something else - probably removed due too compiler optimization
}
}
};

Answer

Example 3 is the snippet that more closely resembles what the compiler is doing. It's important to understand that example 2 is wrong, as the template parameter is evaluated at compile-time and not injected into the class as a field.

Doing if(b){ } else { } where b is a template bool parameter will require both branches of the if statement to be both parseable and well-formed, even if the compiler will very likely optimize out the branch that doesn't match b.


If you want guaranteed compile-time branch evaluation, and if you need only the taken branch to be well-formed, you can use if constexpr(...) in C++17:

if constexpr(b)
{
    // do something
}
else
{
    // do something else
}

...or implement your own static_if construct in C++14...

...or use an explicit template specialization in C++11.

I cover all of these techniques in my CppCon 2016 talk, "Implementing static control flow in C++14".