Blag

He's not dead, he's resting

C++ Template Specialisation Hate

Today’s annoying C++ feature is that partial specialisations of a nested type of a template class don’t work:

template <typename T_>
struct S;

template <typename T_>
struct T
{
    struct U;
};

template <typename T_>
struct S<typename T<T_>::U>
{
};

Depending upon your compiler, the specialisation will either be rejected with a highly cryptic error message, or accepted but ignored. I don’t seem to be able to find the part of the standard that bans doing this, either, but that doesn’t necessarily mean it’s legal…

The solution, in any case, is to hoist the nested class out of the template, and use a typedef instead:

template <typename T_>
struct S;

template <typename T_>
struct T_U;

template <typename T_>
struct T
{
    typedef T_U<T_> U;
};

template <typename T_>
struct S<T_U<T_> >
{
};

I’ve been of the opinion that nested classes are generally far more pain than they’re worth for a while now (they also can’t be forward-declared); I’m highly tempted to just stop using them anywhere at all, and switch exclusively to using typedefs.

Advertisements

2 responses to “C++ Template Specialisation Hate

  1. David Tardon November 29, 2009 at 9:27 am

    IMHO the problem is that U is dependent name in the context
    where you’re trying to use it. The right solution is to use
    typename:


    template <typename T_>
    struct S<typename T<T_>::U>
    {
    };

    • Ciaran McCreesh November 29, 2009 at 4:40 pm

      I tried that too (first, in fact — that was what I meant to paste, but I’d forgotten I’d temporarily changed it not to use typename just to see what happened when I did the colourising). It still doesn’t work. The pattern matching used to deduce which template to use simply isn’t smart enough.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s