Steve
Steve

Reputation: 6424

How do I provide specialization of template function for a templated type?

I have a template function that I'd like to provide a specialization for, in order to handle boost::optional<T>. However, I can't seem to figure out the proper syntax for this scenario, if I want to allow my specialization to handle all types of boost::optional<T>, instead of a specific one like boost::optional<int>.

Here's a compilable example:

#include <boost/optional.hpp>

template <typename T>
void foo(const T& t)
{}

// This works.
template<>
void foo<int>(const int& t)
{}

// This works.
template<>
void foo<boost::optional<int>>(const boost::optional<int>& t)
{}

// What to do in this case??
// template <typename U>
// void foo<boost::optional<U>>(const boost::optional<U>& t)
// {}

int main() {}

Upvotes: 1

Views: 392

Answers (2)

Jarod42
Jarod42

Reputation: 217275

You cannot partial specialize template function. But you can do it for class

namespace detail
{
    template <typename T>
    struct foo_impl
    {
        void operator () (const T&) const {};
    }

    template <>
    struct foo_impl<int> // Full specialization for int
    {
        void operator () (int) const {};
    }

    template <>
    struct foo_impl<boost::optional<int>> // Full specialization for boost::optional<int>
    {
        void operator () (const boost::optional<int>&) const {};
    }

    template <typename T>
    struct foo_impl<boost::optional<T>> // Partial specialization for boost::optional<T>
    {
        void operator () (const boost::optional<T>&) const {};
    }

}

template <typename T>
void foo(const T& t)
{
    detail::foo_impl<T>{}(t); // Forward to correct struct
}

else you can provide overload (which may be simpler)

template <typename T>
void foo(const T&) {}

void foo(int) {}

void foo(const boost::optional<int>&) {}

template <typename T>
void foo(const boost::optional<T>&) {}

Note about the overload method:

- `foo(42)` and `foo<int>(42)` won't call the same function
- and similarly, with `boost::optional<int> opt_i;`,  
    `foo(opt_i)`, `foo<int>(opt_i)` and `foo<boost::optional<int>>(opt_i)`
     will call 3 different functions.

Upvotes: 2

Pradhan
Pradhan

Reputation: 16737

Don't specialize. Provide an overload instead.

template <typename U>
void foo(const boost::optional<U>& t)
{
}

Upvotes: 5

Related Questions