Skip to content

Instantly share code, notes, and snippets.

@kikairoya
Forked from gintenlabo/make_array.cc
Created December 20, 2010 10:01
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 kikairoya/748210 to your computer and use it in GitHub Desktop.
Save kikairoya/748210 to your computer and use it in GitHub Desktop.
#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