Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specialise template method with type that itself is a template where only the return type relies on the template type?

Tags:

c++

templates

I want to specialise a single template method in a non-template class to use an std::vector however only the return type of the method uses the template.

#include <iostream>
#include <string>
#include <vector>

class Foo
{
public:
    template<typename T>
    T Get()
    {
        std::cout << "generic" << std::endl;
        return T();
    }
};

template<>
int Foo::Get()
{
    std::cout << "int" << std::endl;
    return 12;
}

template<typename T>
std::vector<T> Foo::Get()
{
    std::cout << "vector" << std::endl;
    return std::vector<T>();
}

int main()
{
    Foo foo;
    auto s = foo.Get<std::string>();
    auto i = foo.Get<int>();
}

This compiles with an error indicating that the std::vector attempted specialisation does not match any prototype of Foo, which is completely understandable.

In case it matters, use of C++14 is fine and dandy.

like image 215
NeomerArcana Avatar asked Jan 16 '26 21:01

NeomerArcana


1 Answers

You can only partially specialize classes (structs) (cppreference) - so the way to overcome your problems is to add helper struct to allow this partial specialization of std::vector<T> - e.g. this way:

class Foo
{
private: // might be also protected or public, depending on your design
    template<typename T>
    struct GetImpl
    {
        T operator()()
        {
            std::cout << "generic" << std::endl;
            return T();
        }
    };
public:
    template<typename T>
    auto Get()
    {
        return GetImpl<T>{}();
    }
};

For int - you can fully specialize this function:

template<>
int Foo::GetImpl<int>::operator()()
{
    std::cout << "int" << std::endl;
    return 12;
}

For std::vector<T> you have to specialize entire struct:

template<typename T>
struct Foo::GetImpl<std::vector<T>>
{
    std::vector<T> operator()()
    {
        std::cout << "vector" << std::endl;
        return std::vector<T>();
    }
};
like image 103
PiotrNycz Avatar answered Jan 19 '26 12:01

PiotrNycz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!