SirGuy
SirGuy

Reputation: 10770

c++ break template specialization ambiguity

I have been reading through C++ Template Metaprogramming and doing the exercises contained therein and have come across a problem. The core of the problem can be seen with this small example:

    template <class A, class B>
    struct C;

    template <class A>
    struct C<A,A>
    {
      typedef some_type type;
    };

    template <class A, class B>
    struct C<A*,B>
    {
      typedef some_other_type type;
    };

    int main()
    {
      C<int*,int*> c;
    }

This fails to compile because c's type is ambiguous. The compiler can't tell which specialization it's suppose to instantiate, however, I know that in a case like this I want the first specialization to be called. The solution I've come up with so far is to rewrite it like this

    template <class A, class B>
    struct C;

    template <class A, class B>
    struct C<A*,B>
    {
      typedef typename boost::mpl::if_c<boost::is_same<A*,B>::value,
                                        some_type, some_other_type>::type type;
    };

The problem with this solution is that I actually have partial specializations for each of pointer, const, reference and array types, so I've had to add this check to each specialization individually.

My question is, then, is there some way to have the nice compact specializations of before and somehow tweak it so that the compiler instantiates the specialization

     template <class A>
     struct C<A,A>
     {
       typedef some_type type;
     };

instead of any of the other specializations in case of ambiguity?

For those interested the question I'm working on is Chapter 2 question 1.

Upvotes: 2

Views: 1256

Answers (1)

BigBoss
BigBoss

Reputation: 6914

You may add another parameter to your base template and use it to enable/disable your specialization. For example you may have:

template< class A, class B, class Enable = void >
struct C;
template< class A >
struct C<A, A, void> {...};
template< class A, class B >
struct C<A*, B, typename boost::disable_if<boost::is_same<A*, B> >::type> {...};

Now if you want to handle const pointer or any thing else you may extend your condition according to type traits(is_const, is_pointer, ...)!

Upvotes: 2

Related Questions