. S ( , , - ). , , .
template <typename, typename...> struct Sort;
template <typename T, typename A, typename B>
struct Sort<T,A,B> {
using type = typename Merge<T,A,B>::type;
};
template <typename T, typename First, typename Second, typename... Rest>
struct Sort<T, First, Second, Rest...> {
using type = typename Sort<T, typename Sort<T, First, Second>::type, Rest...>::type;
};
.
struct Widget : Sort<PossibleActions<0,5>, OneAndFour, TwoAndThree>
. :
#include <iostream>
namespace Detail {
template <typename T, typename, typename, T...> struct Merge;
template <typename T, template <T...> class S, T... Ks>
struct Merge<T, S<>, S<>, Ks...> {
using type = S<Ks...>;
};
template <typename T, template <T...> class S, T... Is, T... Ks>
struct Merge<T, S<Is...>, S<>, Ks...> {
using type = S<Ks..., Is...>;
};
template <typename T, template <T...> class S, T... Js, T... Ks>
struct Merge<T, S<>, S<Js...>, Ks...> {
using type = S<Ks..., Js...>;
};
template <typename T, bool, typename, typename, T...> struct Strip;
template <typename T, template <T...> class S, T I, T... Is, T J, T... Js, T... Ks>
struct Strip<T, true, S<I, Is...>, S<J, Js...>, Ks...> {
using type = Merge<T, S<I, Is...>, S<Js...>, Ks..., J>;
};
template <typename T, template <T...> class S, T I, T... Is, T J, T... Js, T... Ks>
struct Strip<T, false, S<I, Is...>, S<J, Js...>, Ks...> {
using type = Merge<T, S<Is...>, S<J, Js...>, Ks..., I>;
};
template <typename T, template <T...> class S, T I, T... Is, T J, T... Js, T... Ks>
struct Merge<T, S<I, Is...>, S<J, Js...>, Ks...> : Strip<T, (I > J), S<I, Is...>, S<J, Js...>, Ks...>::type {};
template <typename, typename...> struct Sort;
template <typename T, typename A, typename B>
struct Sort<T,A,B> {
using type = typename Merge<T,A,B>::type;
};
template <typename T, typename First, typename Second, typename... Rest>
struct Sort<T, First, Second, Rest...> {
using type = typename Sort<T, typename Sort<T, First, Second>::type, Rest...>::type;
};
}
template <typename... P>
using Sort = typename Detail::Sort<int, P...>::type;
struct ActionOption {
virtual void foo(int) const = 0;
};
template <int> struct ActionType;
template <> struct ActionType<0> : ActionOption {
virtual void foo(int) const override {std::cout << "ActionType<0>::foo(int) called.\n";}
};
template <> struct ActionType<1> : ActionOption {
virtual void foo(int) const override {std::cout << "ActionType<1>::foo(int) called.\n";}
};
template <> struct ActionType<2> : ActionOption {
virtual void foo(int) const override {std::cout << "ActionType<2>::foo(int) called.\n";}
};
template <> struct ActionType<3> : ActionOption {
virtual void foo(int) const override {std::cout << "ActionType<3>::foo(int) called.\n";}
};
template <> struct ActionType<4> : ActionOption {
virtual void foo(int) const override {std::cout << "ActionType<4>::foo(int) called.\n";}
};
template <> struct ActionType<5> : ActionOption {
virtual void foo(int) const override {std::cout << "ActionType<5>::foo(int) called.\n";}
};
template <int...> struct PossibleActions;
template <> struct PossibleActions<> { void operator()(int) const {} };
template <int First, int... Rest>
struct PossibleActions<First, Rest...> : ActionType<First>, PossibleActions<Rest...> {
void operator()(int a) const {
ActionType<First>::foo(a);
PossibleActions<Rest...>::operator()(a);
}
};
using OneAndFour = PossibleActions<1,4>;
using TwoAndThree = PossibleActions<2,3>;
struct Thing : PossibleActions<0,1,2,3,4> {
void foo(int a) {PossibleActions<0,1,2,3,4>::operator()(a);}
};
struct Object : Sort<PossibleActions<1,4>, TwoAndThree> {
void foo(int a) {Sort<PossibleActions<1,4>, TwoAndThree>()(a);}
};
struct Blob : Sort<PossibleActions<0,4>, TwoAndThree> {
void foo(int a) {Sort<PossibleActions<0,4>, TwoAndThree>()(a);}
};
struct Widget : Sort<PossibleActions<0,5>, OneAndFour, TwoAndThree> {
void foo(int a) {Sort<PossibleActions<0,5>, OneAndFour, TwoAndThree>()(a);}
};
int main() {
Thing thing;
thing.foo(12);
std::cout << std::endl;
Object object;
object.foo(12);
std::cout << std::endl;
Blob blob;
blob.foo(12);
std::cout << std::endl;
Widget widget;
widget.foo(12);
}
, , , . , , , .