C ++ - partial specialization of a variational pattern

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"; }
};

What can I use this way:

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

Correctly returns "ABC". But when I declare A<int, double, double> d;, I get an explicit compile-time error ambiguous class template instantiation for struct A<int, double, double>.

Question: Is it possible to do some kind of trick (possibly using SFINAE) to take into account the second argument of the template, since it will have a higher priority and the specification returning B will be used? (Ignoring type doublein third position)

NOTE: types doubleand intare used to simplify the example, I will use type properties. And so I would like to avoid specialization as a solution:

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

, SFINAE, C, 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...>;
+2

Source: https://habr.com/ru/post/1627921/


All Articles