Skip to content

Instantly share code, notes, and snippets.

@thefloweringash
Created June 25, 2012 12:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thefloweringash/2988405 to your computer and use it in GitHub Desktop.
Save thefloweringash/2988405 to your computer and use it in GitHub Desktop.
Winning at templates?
#include <iostream>
using namespace std;
template <typename... T>
struct pp {};
template <typename T, typename TI,
typename U, typename UI,
typename F>
struct matcher;
template <typename T, typename... TI,
typename U, typename... UI,
typename F>
struct matcher<T, pp<TI...>,
U, pp<UI...>,
F> {
matcher(TI... ti, UI... ui, F i) {
// static_assert(sizeof...(ti) == 1, "ti has length 1");
// static_assert(sizeof...(ui) == 1, "ui has length 1");
// T t(ti...);
// U u(ui...);
cout << "TI size = " << sizeof...(ti) << endl
<< "UI size = " << sizeof...(ui) << endl;
// << "i = " << i << endl; // uncommenting this crashes clang for me
}
};
struct int_arg {
using init = pp<int>;
int_arg(int x) {}
};
struct no_arg {
using init = pp<>;
no_arg(){}
};
template <typename T> struct has_init {
using yes = char[1];
using no = char[2];
template <typename U> static yes& f(typename U::init*){}
template <typename U> static no& f(U*){}
static constexpr bool value =
sizeof(yes) == sizeof(f<T>(0));
};
template <typename T>
struct nodelay {
using type = T;
};
template <typename T>
struct delay_init {
using type = typename T::init;
};
template <bool B, typename X, typename Y>
struct lazy_template_if {
using type = typename X::type;
};
template <typename X, typename Y>
struct lazy_template_if<false, X, Y> {
using type = typename Y::type;
};
template <template <typename...> class Con,
typename Accum,
typename...>
struct splice_inits_worker;
template <template <typename...> class Con,
typename... Accum,
typename T, typename... TS
>
struct splice_inits_worker<Con, pp<Accum...>, T, TS...> {
using type = typename lazy_template_if<has_init<T>::value,
splice_inits_worker<Con, pp<Accum..., nodelay<T>, delay_init<T>>, TS...>,
splice_inits_worker<Con, pp<Accum..., nodelay<T>>, TS...>
>::type;
};
template <template <typename...> class Con,
typename... Accum>
struct splice_inits_worker<Con, pp<Accum...>> {
using type = Con<typename Accum::type...>;
};
template <template <typename...> class Con,
typename... XS>
using splice_inits = splice_inits_worker<Con, pp<>, XS...>;
using testNI = splice_inits<matcher, no_arg, int_arg, int>::type;
using testIN = splice_inits<matcher, int_arg, no_arg, int>::type;
using testII = splice_inits<matcher, int_arg, int_arg, int>::type;
int main() {
testNI(1, 1337);
testIN(1, 1337);
testII(1,1, 1337);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment