Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - variadic template partial specialization

Let's have a simple snippet:

template<class T, class... Args>
struct A {
    void operator()() { std::cout << "A"; }
};

template<class T, class... Args>
struct A<T, double, Args...> {
    void operator()() { std::cout << "B"; }
};

template<class T, class B, class... Args>
struct A<T, B, double, Args...> {
    void operator()() { std::cout << "C"; }
};

Which i can use in this way:

int main() {
    A<int, int, int> a;
    A<int, double, int> b;
    A<int, int, double> c;
    a(); b(); c();
    return 0;
}

It properly returns "ABC". But when i declare A<int, double, double> d; i get obviously compile time error ambiguous class template instantiation for struct A<int, double, double>.

The question is: can i do some trick (probably using SFINAE) to take into account the second template argument as it would have a higher priority and specialization returning B would be used? (Ignoring type double on third position)

NOTE: types double and int are used to make example simpler, i will use type traits. And therefore i would like to avoid following specialization as a solution:

template<class T, class... Args>
struct A<T, double, double, Args...> {
    void operator()() { std::cout << "D"; }
};
like image 427
Radek Avatar asked Oct 18 '22 16:10

Radek


1 Answers

As you suggest, you can use SFINAE to not consider the C specialization if the second template argument is double:

template<typename, class T, class... Args>
struct A_impl {
    void operator()() { std::cout << "A"; }
};

template<class T, class... Args>
struct A_impl<void, T, double, Args...> {
    void operator()() { std::cout << "B"; }
};

template<class T, class B, class... Args>
struct A_impl<typename std::enable_if<!std::is_same<B,double>::value>::type,
         T, B, double, Args...> {
    void operator()() { std::cout << "C"; }
};

template<class T,class... Args>
using A = A_impl<void,T,Args...>;
like image 147
TartanLlama Avatar answered Oct 21 '22 22:10

TartanLlama