Reputation: 149
For simplicity, say I usually want to pass in strings and basic data types in here:
template <typename T>
void writeLine(const T &ob)
{
std::cout << ob << std::endl;
}
In most cases, I would pass std::string, int, char, float, etc. But say that I don't want it to accept floats. In real world scenarios, I may not want it to accept certain classes.
Is there a way to restrict what the template type accepts?
Upvotes: 4
Views: 8423
Reputation: 12928
Yes you can, the most simple way for your example is to put a static_assert
in your function.
template <typename T>
void writeLine(const T &ob)
{
static_assert(!std::is_same<T, float>::value, "You can't use floats here");
std::cout << ob << std::endl;
}
This will give you a compile time error if you try and use the function with a float.
Another option is called SFINAE and is used to make the template parameter deduction fail under certain circumstances.
Usually you use std::enable_if in combination with some templates from <type_traits>
header. The same thing with SFINAE would look something like:
template <typename T, typename std::enable_if<!std::is_same<T, float>::value, int>::type = 0>
void writeLine(const T &ob)
{
std::cout << ob << std::endl;
}
Let's break down typename std::enable_if<!std::is_same<T, float>::value, int>::type
.
!std::is_same<T, float>::value
is the condition here, if this condition is true this template will have a ::type
, otherwise it will not.
After the condition we can specify what we want the type to be if the condition is true, in this case we use int
. If this is not specified it will default to void
.
So as long as we don't pass a float to this template, the second template parameter will be deduced to int = 0
. If we pass in a float the deduction will simply fail and you will get a no matching function
error showing the template as a candidate with failed deduction.
Upvotes: 13