Recently, I was discussing with students the possibilities of restriction of types for templates that uses forwarding references. I knew about comparing types by is_same
together with static_assert
or enable_if
, but we also talked about explicit template instantiation.
The following example works for me with GCC:
f.h:
template <typename T>
void f(T&& param); // declaration
f.cpp:
#include <iostream>
template <typename T>
void f(T&& param) { std::cout << param << std::endl; }
// explicit instantiations:
template void f<int>(int&&);
template void f<int&>(int&);
main.cpp:
#include "f.h"
int main() {
f(1);
// f('1'); // LINKER ERROR
int i = 2;
f(i);
}
I am not an expert in explicit template instantiations, so I just wonder whether such a solution is portable/standard-compliant. (Please, do not ask me about use cases, I don't have any. For me, it's purely an academic question.)
UPDATE
I am also a bit confused about the format of the explicit instantiation (<int>(int&&)
and <int&>(int&)
), but I guess that it is given by template deduction and maybe reference collapsing rules.
This is okay and it is portable/standard-compliant.
This is called template specialization and you can read more on this topic here
Template specialization is writing a specific handler for a specific invoke.
In your code, you have two specializations.
The first receives a rvalue reference(e.g. integer literal like 5) and returns an int
.
The second one receives a lvalue reference(e.g. the variable b who is of type int an have a value of 5) and returns a lvalue reference.
In the default case, you're trying to print the param using std::stringstream
.