The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
What is a type trait? A type trait is a simple template struct that contains a member constant, which in turn holds the answer to the question the type trait asks or the transformation it performs.
Consider the following example:
struct Scanner
{
template <typename T>
T get();
};
template <>
string Scanner::get()
{
return string("string");
}
template <>
int Scanner::get()
{
return 10;
}
int main()
{
Scanner scanner;
string s = scanner.get<string>();
int i = scanner.get<int>();
}
The Scanner
class is used to extract tokens from some source. The above code works fine, but fails when I try to get
other integral types like a char
or an unsigned int
. The code to read these types is exactly the same as the code to read an int
. I could just duplicate the code for all other integral types I'd like to read, but I'd rather define one function template for all integral types.
I've tried the following:
struct Scanner
{
template <typename T>
typename enable_if<boost::is_integral<T>, T>::type get();
};
Which works like a charm, but I am unsure how to get Scanner::get<string>()
to function again. So, how can I write code so that I can do scanner.get<string>()
and scanner.get<any integral type>()
and have a single definition to read all integral types?
Update: bonus question: What if I want to accept more than one range of classes based on some traits? For example: how should I approach this problem if I want to have three get
functions that accept (i) integral types (ii) floating point types (iii) strings, respectively.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With