vladon
vladon

Reputation: 8401

Specialize template for const T& for big types and T for simple types

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

Answers (5)

Count Zero
Count Zero

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

Edgar Rokjān
Edgar Rokjān

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

WhiZTiM
WhiZTiM

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

EmDroid
EmDroid

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

chedy najjar
chedy najjar

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;
}

see the code here

Upvotes: 1

Related Questions