11
votes
template<typename T1, typename T2>
class Bimap {
public:
    class Data {
    private:
        template<typename T> Data& set(T);
        template<> Data& set<T1>(typename T1 v) { /*...*/ }
    };
};

That gives me the error:

error: explicit specialization in non-namespace scope 'class Bimap<T1, T2>::Data'

I understand what the error is saying. But why I can't I do this? And how can I fix it?

2
Worth noting that some compilers will support this. - Puppy
In C++ you cannot explicitly specialize a member template without explicitly specializing the enclosing class template. What you are trying (namely, specialization) to do is not possible. You have to use overloading. Or redesign the whole thing entirely. MSVC++ is a compiler that allows this as an extension though. - AnT

2 Answers

16
votes

One way forget templates, overload:

Data& set(T1 v) { /*...*/ }

but here is a trick which I use sometimes

you can specialize class template within class:

class {
    template<typename T>
    struct function_ {
        static void apply(T);
    };

    template<>
    struct function_<int> {
        ...
    };

    template<typename T>
    void function(T t) { return function_<T>::apply(t); }
0
votes

@Albert

I had a similar problem when I wanted to add a "trim-excess-capacity" to a custom made container. The std::vector swap trick and changing the declaration of the existing container were not valid options. So I've come up with this:

template <class T, bool isPtr> struct DeleteImp
{
    static void Trim(T* to, unsigned int count);
};

template <class T> struct DeleteImp<T, false>       
{
    static void Trim(T* to, unsigned int count) {}
};

template <class T> struct DeleteImp<T, true>        
{
    static void Trim(T* to, unsigned int count)
    {
        for(unsigned int i=0; i<count; i++)
            delete to[i];
    }
};

used by my container like this:

DeleteImp<T, TypeTraits<T>::isPointer>::Trim(buf + length, truelength-length);

You may also want to check out this resource.