Created
June 25, 2012 12:51
-
-
Save thefloweringash/2988405 to your computer and use it in GitHub Desktop.
Winning at templates?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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