
AMDG Eric Niebler wrote:
I recently had a C++ problem and found an answer that tickled my brain. In the spirit of Car Talk on NPR, I thought I'd share it in the form of a puzzler
Another solution in the mix. All PP magic. I pushed it up to 13 parameters before msvc 9.0 failed. In Christ, Steven Watanabe #include <boost/preprocessor/seq/for_each_product.hpp> #include <boost/preprocessor/seq/enum.hpp> #include <boost/preprocessor/seq/fold_left.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp> #include <boost/preprocessor/control/if.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/logical/and.hpp> #define COMMON_TYPE_LIMIT_PARAMS 4 struct default_t {}; #define IS_DEFAULT_default_t 1 #define IS_DEFAULT_T 0 #define IS_DEFAULT(x) BOOST_PP_CAT(IS_DEFAULT_, x) #define TEST(s, state, elem) BOOST_PP_AND(state, IS_DEFAULT(elem)) #define IS_ALL_DEFAULT(seq) BOOST_PP_SEQ_FOLD_LEFT(TEST, 1, seq) #define WITH_T(args) template<class T> struct common_type<BOOST_PP_SEQ_ENUM(args)> { typedef T type; }; #define DEFAULT(args) template<> struct common_type<BOOST_PP_SEQ_ENUM(args)> { typedef default_t type; }; #define SPECIALIZATION(r, args) BOOST_PP_IF(IS_ALL_DEFAULT(args), DEFAULT, WITH_T)(args) template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(COMMON_TYPE_LIMIT_PARAMS, class T, default_t)> struct common_type {}; #define PARAMETERS(z, n, data) ((T)(default_t)) BOOST_PP_SEQ_FOR_EACH_PRODUCT(SPECIALIZATION, BOOST_PP_REPEAT(COMMON_TYPE_LIMIT_PARAMS, PARAMETERS, ~)) int main() { typedef common_type<int, int, int>::type int1; typedef common_type<int, default_t, int>::type int2; typedef common_type<default_t, int, int, default_t>::type int3; //typedef common_type<default_t, int, char, default_t>::type error1; typedef common_type<>::type default1; }