Let's say we have a dual parametrized template like
template<class A, class B>
class Class { .... };
and that there are specializations for a particular A
and a particular B
template<class B> class Class<A1,B> { .... };
template<class A> class Class<A,B1> { .... };
Now, when I have to instantiate Class<A1,B1>
the compiler complains for ambiguity since it find <A,B1>
and <A1,B>
equally usable.
The problem can of course be eliminated by adding an <A1,B1>
specialization, but -in my context- it will be identical <A1,B>
.
Is there a way to eliminate the ambiguity without repeating the entire <A1,B>
full code?
One possibility is to simply forbid the second specialization to be selected:
template<class A, class B, class=void>
class Class {};
template<class B>
class Class<A1,B> {};
template<class A>
class Class<A, B1, typename std::enable_if<!std::is_same<A,A1>::value>::type> {};
Demo.
I'd add a third default parameter to the base template and allow each specialization to be picked up through SFINAE:
template<class A, class B,
class extra = void /* Enable/disable specialization through SFINAE */>
class Class { public: void hello() {std::cout << "Base" << std::endl;} };
template<class B> class Class<A1, B> {
public:
void hello() {std::cout << "First" << std::endl;}
};
template<class A> class Class<A, B1,
typename std::enable_if<!std::is_same<A, A1>::value>::type> {
public:
void hello() {std::cout << "Second" << std::endl;}
};
int main()
{
Class<A1,B1> obj;// The first one is picked up
obj.hello();
Class<A,B1> obj2; // The second one is picked up
obj2.hello();
Class<A,B> obj3; // Base
obj3.hello();
}
Example
or even simpler (depending if it's acceptable in your use cases):
template<class A, class B, bool AisA1 = std::is_same<A,A1>::value>
class Class { public: void hello() {std::cout << "Base" << std::endl;} };
template<class B> class Class<A1, B, true /* Pick this when A == A1 */> {
public: void hello() {std::cout << "First" << std::endl;}
};
template<class A> class Class<A, B1, false> {
public: void hello() {std::cout << "Second" << std::endl;}
};
Example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With