Reputation: 8401
I need to do this magic:
I have a template:
template <class T>
void Foo(const T& value)
But I need to specialize it for simple types, for example, bool
, int
, etc so it will be passed by const value, not by const reference:
template <>
void Foo<bool>(const bool value)
template <>
void Foo<int>(const int value)
// and so on, including std::nullptr_t
template <>
void Foo<std::nullptr_t>(std::nullptr_t)
{
// some special behavior
}
But it cannot be compiled.
How to do it correctly?
Upvotes: 1
Views: 508
Reputation: 545
Maybe this helps:
template<typename T>
void foo(conditional_t<is_fundamental_v<T> || is_pointer_v<T>, const T, const T&> x)
{
//do stuff
}
Upvotes: 1
Reputation: 17483
If the functionality for all fundamental types and pointers is the same I guess you can make use of std::is_fundamental, std::is_pointer and std::enable_if:
template<typename T>
std::enable_if_t<std::is_fundamental<T>::value || std::is_pointer<T>::value>
foo(const T) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
template<typename T>
std::enable_if_t<!std::is_fundamental<T>::value && !std::is_pointer<T>::value>
foo(const T&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
Example on wandbox
Upvotes: 5
Reputation: 21576
You can also use tagged dispatch and perfect forwarding....
template<typename T>
void Foo_dispatch(T val, std::true_type){
std::cout << val << " Passed by value\n";
}
template<typename T>
void Foo_dispatch(const T& val, std::false_type){
std::cout << val << " Passed by reference\n";
}
void Foo(std::nullptr_t){}
template <class T>
void Foo(T&& value){
using type = std::integral_constant<bool, std::is_fundamental<T>::value || std::is_pointer<T>::value>;
Foo_dispatch(std::forward<T>(value), type());
}
Example Usage:
int main(){
Foo(23);
Foo(45.343);
Foo("Hahah");
Foo(std::string("Cool stuff"));
Foo(nullptr);
Foo(&"huhu");
}
Produces:
23 Passed by value
45.343 Passed by value
Hahah Passed by reference
Cool stuff Passed by reference
nullptr_t gotten
0x400e52 Passed by value
See it Live
Upvotes: 2
Reputation: 6066
It's because
void Foo<bool>(const bool value)
is not specialization of
template <class T>
void Foo(const T& value)
but it is its overload (with functions it is different from class templates, because functions can overload).
What you can do is for example:
template <class T>
struct Foo {
void operator ()(const T& value);
};
template <>
struct Foo<bool> {
void operator ()(bool value);
};
// ... other specializations
(or just use simple non-templated overloads, as they take precedence over template instantiation)
Upvotes: 1
Reputation: 631
you can do this :
template <class T>
void Foo(const T& value)
{
return ;
}
void Foo(const bool value)
{ }
void Foo(const int value)
{ }
// and so on, including std::nullptr_t
void Foo(std::nullptr_t)
{
// some special behavior
}
int main( ) {
Foo(1);
Foo(true);
Foo(nullptr);
return 0;
}
Upvotes: 1