Restrict Template Function
The only way to restrict a template is to make it so that it uses something from the types that you want, that other types don't have.
So, you construct with an int, use + and +=, call a copy constructor, etc.
Any type that has all of these will work with your function -- so, if I create a new type that has these features, your function will work on it -- which is great, isn't it?
If you want to restrict it more, use more functions that only are defined for the type you want.
Another way to implement this is by creating a traits template -- something like this
template<class T>
SumTraits
{
public:
const static bool canUseSum = false;
}
And then specialize it for the classes you want to be ok:
template<>
class SumTraits<int>
{
public:
const static bool canUseSum = true;
};
Then in your code, you can write
if (!SumTraits<T>::canUseSum) {
// throw something here
}
edit: as mentioned in the comments, you can use BOOST_STATIC_ASSERT to make it a compile-time check instead of a run-time one
How do I restrict templates to specific types?
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.
c++ function template restrict parameter type
Using enable_if
you could write the function like
template <typename arg_t, std::enable_if_t<std::is_same_v<std::decay_t<arg_t>, int> ||
std::is_same_v<std::decay_t<arg_t>, std::string>,
bool> = true>
void func(arg_t arg){}
C++ templates that accept only certain types
I suggest using Boost's static assert feature in concert with is_base_of
from the Boost Type Traits library:
template<typename T>
class ObservableList {
BOOST_STATIC_ASSERT((is_base_of<List, T>::value)); //Yes, the double parentheses are needed, otherwise the comma will be seen as macro argument separator
...
};
In some other, simpler cases, you can simply forward-declare a global template, but only define (explicitly or partially specialise) it for the valid types:
template<typename T> class my_template; // Declare, but don't define
// int is a valid type
template<> class my_template<int> {
...
};
// All pointer types are valid
template<typename T> class my_template<T*> {
...
};
// All other types are invalid, and will cause linker error messages.
[Minor EDIT 6/12/2013: Using a declared-but-not-defined template will result in linker, not compiler, error messages.]
How to restrict template class to only specific specializations with type aliases
Best scenario I would like to achieve would be to make Wrapper class not visible outside the usage of aliases I create.
This is possible using private
and a wrapper class
class WrapperAccessor {
template < typename Type >
class Wrapper {
public:
Wrapper(Type* resource) : ptr(resource) {}
~Wrapper() { free(ptr); }
private:
Type* ptr;
};
public:
using Window = Wrapper<SDL_Window>;
using Renderer = Wrapper<SDL_Renderer>;
};
using Window = WrapperAccessor::Window;
using Renderer = WrapperAccessor::Renderer;
How to restrict a template function from being called if the type is not a pointer?
If you just want to find out, where your class is erroneously used with a non-pointer template parameter type, you can use static_assert
:
template<class t>
class List {
static_assert(!std::is_pointer<t>::value, "Template parameter must be of pointer type");
//other stuff
};
If you want the ClearAndDelete()
function to be usable with pointer and non-pointer types, you could e.g. use something like this:
template<class T>
void deleteIfPointer(const T& element) {}
template<class T>
void deleteIfPointer(T* ptr) {
delete ptr;
}
usage:
deleteIfPointer(ptr->Item); //instead of delete ptr->Item
On a side note: Usually containers should not delete objects that their elements point to (If you need this behavior, you might want to use std::unique_ptr
instead).
Restrict function template to specific types?
The typical answer these days is this. To define the function with an extra template parameter that will make the function be ignored if the dummy type constructed from the expression doesn't exist.
template <typename T, typename = decltype(std::to_string(std::declval<T>()))>
std::string operator+(std::string & lhs, T && t)
{
...
}
It can be more refined by it does what you want.
Another more elegant syntax is this
template <typename T>
auto operator+(std::string & lhs, T && t) -> decltype(std::to_string(t))
{
...
}
This exploits a language feature called SFINAE.
Related Topics
How to Set Error_Code to Asio::Yield_Context
How to Specify Vc11 Lambda Calling Convention
Sorting a List of a Custom Type
What Is the Meaning of Double Curly Braces Initializing a C-Struct
What Are the Advantages and Disadvantages of Implementing Classes in Header Files
What Are the Reasons That Extending the Std Namespace Is Considered Undefined Behavior
How to Convert a Value from Host Byte Order to Little Endian
What Is the Simplest Way to Convert Char[] To/From Tchar[] in C/C++(Ms)
Why Class Size Depend Only on Data Members and Not on Member Functions
How to Call a Cmake Function from Add_Custom_Target/Command
Multiple "Could Not Be Resolved" Problems Using Eclipse with Mingw
Generate N Random Numbers Within a Range with a Constant Sum
Mingw Error: 'Thread' Is Not a Member of 'Std'
Debug Assertion Failed! Expression: _Block_Type_Is_Valid
C++ "Hello World" Boost Tee Example Program
Why How to Call a Non-Constexpr Function Inside a Constexpr Function