11
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
  • 3
    Worth noting that some compilers will support this. Commented Sep 19, 2010 at 16:20
  • 1
    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. Commented Sep 19, 2010 at 17:01

2 Answers 2

16

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); }
Sign up to request clarification or add additional context in comments.

3 Comments

+1, yeah, the only sane way to get function template specializations right.
You can explicitly specialize a nested class template within an ordinary class. But you cannot explicitly specialize a nested class template within another class template. The only way to do the latter is to explicitly specialize both the enclosing template and the nested template.
@Andrey I was not sure about template class inside template class. at any rate, some variation of the trick can probably be made
0

@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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.