template T declval(); struct nil_ { constexpr nil_() {} }; constexpr nil_ nil; template struct cons_ { constexpr cons_() {} constexpr cons_(H const& x, T const& y) : head(x), tail(y) {} H head; T tail; }; template constexpr cons_ cons(H const& h, T const& t) { return cons_(h,t); } #define RETURNS_CAT_0(x, y) x ## y #define RETURNS_CAT(x, y) RETURNS_CAT_0(x,y) #define RETURNS(...) -> decltype(__VA_ARGS__) { return (__VA_ARGS__); } typedef int RETURNS_CAT(RETURNS_, __LINE__) constexpr auto list() RETURNS( nil ); template constexpr auto list(T x) RETURNS( cons(x, nil) ); #ifndef WORKAROUND template constexpr auto list(H h, T ...args) RETURNS(cons( h, list( args... ) )); #else template struct list_; template struct list_ { using type = cons_::type>; }; template <> struct list_<> { using type = nil_; }; // Used to prove we're calculating the type correctly template struct assert_same; template struct assert_same{}; template constexpr auto list(H h, T ...args) -> typename list_::type { return assert_same< decltype(cons( h, list(args...) )), typename list_::type >(), cons( h, list(args...) ); } #endif auto list3 = list(1, 2, 3); int main() {}