-
-
Save kikairoya/748210 to your computer and use it in GitHub Desktop.
This file contains 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 <array> | |
#include <type_traits> | |
template <typename U, typename ...Args> | |
struct make_array_impl_ { | |
template <typename T, typename Void, typename NonVoid> | |
struct if_void_else { typedef NonVoid type; }; | |
template <typename Void, typename NonVoid> | |
struct if_void_else<void, Void, NonVoid> { typedef Void type; }; | |
template <typename T = void, typename ElemT = typename if_void_else<T, U, T>::type > | |
std::array<ElemT, sizeof...(Args)+1> exec(U &&x, Args &&...args) { return std::array<ElemT, sizeof...(Args)+1>{{ std::forward<U>(x), std::forward<Args>(args)... }}; } | |
template <typename T = void> | |
struct get_array_type { typedef std::array<typename if_void_else<T, U, T>::type, sizeof...(Args)+1> type; }; | |
}; | |
template <typename U, typename ...Args> | |
make_array_impl_<U, Args...> make_array_impl_helper_(U &&, Args &&...); | |
template <typename T = void, typename U, typename ...Args> | |
typename make_array_impl_<U, Args...>::template get_array_type<T>::type make_array(U &&x, Args &&...args) { | |
typedef typename make_array_impl_<U, Args...>::template get_array_type<T>::type ArrayT; | |
return ArrayT{{ std::forward<U>(x), std::forward<Args>(args)... }}; | |
} | |
#define make_auto_array(...) decltype(make_array_impl_helper_(__VA_ARGS__).exec<void>(__VA_ARGS__)){{__VA_ARGS__}} | |
#define make_exact_array(T, ...) decltype(make_array_impl_helper_(__VA_ARGS__).exec<T>(__VA_ARGS__)){{__VA_ARGS__}} | |
#include <typeinfo> | |
#include <iostream> | |
#include <algorithm> | |
struct object { | |
object(): value(0) { std::cout << "def-ctor\n"; } | |
object(int v): value(v) { std::cout << "ctor( " << value << " )\n"; } | |
object(object &&o) { std::cout << "move-ctor( " << o.value << " )\n"; value = o.value; o.value = -value; } | |
object(const object &o) { std::cout << "copy-ctor( " << o.value << " )\n"; value = o.value; } | |
object &operator =(object &&o) { std::cout << "move-assign( " << o.value << " to " << value << " )\n"; value = o.value; o.value = -value; return *this; } | |
object &operator =(const object &o) { std::cout << "copy-assign( " << o.value << " to " << value << " )\n"; value = o.value; return *this; } | |
~object() { std::cout << "destructor( " << value << " )\n"; } | |
int value; | |
}; | |
int main() { | |
{ // one-phase construction with macro, specify element type explicitly | |
auto a = make_exact_array(object, object(1), object(2), object(3)); | |
std::cout << typeid(a).name() << '\n'; | |
std::for_each(a.begin(), a.end(), [](const object &o) { | |
std::cout << o.value << ", "; | |
}); | |
std::cout << '\n'; | |
} { // one-phase construction with macro, element type is auto detected | |
auto a = make_auto_array(object(1), object(2), object(3)); | |
std::cout << typeid(a).name() << '\n'; | |
std::for_each(a.begin(), a.end(), [](const object &o) { | |
std::cout << o.value << ", "; | |
}); | |
std::cout << '\n'; | |
} { // two-phase construction without macro, specify element type explicitly | |
auto a = make_array<object>(object(1), object(2), object(3)); | |
std::cout << typeid(a).name() << '\n'; | |
std::for_each(a.begin(), a.end(), [](const object &o) { | |
std::cout << o.value << ", "; | |
}); | |
std::cout << '\n'; | |
} { // two-phase construction without macro, element type is auto detected | |
auto a = make_array(object(1), object(2), object(3)); | |
std::cout << typeid(a).name() << '\n'; | |
std::for_each(a.begin(), a.end(), [](const object &o) { | |
std::cout << o.value << ", "; | |
}); | |
std::cout << '\n'; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment