Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function specialized with template

I need to make a specialization of my function with template class and have problem with "illegal use of explicit template arguments".

template <typename T>
class MyClass { /* ... */ }; // it can be any template class, eg std::vector

template <typename T>
void foo() { /* ... */ } // my template function which need a specialization

template<> 
void foo<int>() /* sth special for integers - it works */ }

template<template T> 
void foo<MyClass<T> >() /* sth special for template class with any parameter - it doesnt work :( */ }

Of course i can type a few specialization for all MyClass'es which i need to, but maybe it can be replaced with one?

like image 573
yzz Avatar asked May 08 '14 18:05

yzz


People also ask

What is function template specialization?

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 the use of a function template?

Function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type. In C++ this can be achieved using template parameters.

What does function template mean?

Function templates are similar to class templates but define a family of functions. With function templates, you can specify a set of functions that are based on the same code but act on different types or classes.

Can we use template in main function?

main cannot be a function template; it must be a function.


3 Answers

Template specialization of function is not as flexible as specialization of struct: only full specialization is allowed. If you want to do partial specialization you need to wrap your foo function inside a struct:

template <typename T> class MyClass { };

template <typename T> struct Foo;

template <typename T> struct Foo { void foo() {}};

template<> struct Foo<int> { void foo() { } };

template<typename T> struct Foo< MyClass<T> > { void foo() {} };

And then instead of calling

foo<MyClass<...>>()

you call

Foo< MyClass<...> >::foo()
like image 154
hivert Avatar answered Sep 22 '22 16:09

hivert


You cannot partially speciallise a template function. There are discussions about removing that restriction though.

The advocated workarounds are:

  1. Use a class template from the template function.
  2. Wrap your function in a template class.
template <typename T>
struct foo_impl {
};
template <typename T>
void foo() {
    foo_impl<T>();
}

// And now specialize foo_impl as you want:

template<>
struct foo_impl<int> {
    foo_impl(){/* sth special for integers - it works */}
};
template<typename T>
struct foo_impl<myclass<T>> {
   foo_impl() {/* ... */}
};

If you wanted a return-value, you should use a member-function - probably operator() - instead of the ctor.

like image 21
Deduplicator Avatar answered Sep 18 '22 16:09

Deduplicator


This is a lot of extra typing, but how about:

template <typename T>
class MyClass { /* ... */ }; // it can be any template class, eg std::vector

template<typename T>
struct FooWrapper
{
    static void foo()
    {
       // default implementation
    }
};

template<typename T>
struct FooWrapper<MyClass<T>>
{
    static void foo()
    {
        // MyClass<T> implementation
    }
};

template<typename T>
void foo()
{
    FooWrapper<T>::foo();
}
like image 39
dlf Avatar answered Sep 22 '22 16:09

dlf