Last active
October 20, 2015 07:26
-
-
Save nekko1119/4c9065dec12f1d6d639b to your computer and use it in GitHub Desktop.
https://www.youtube.com/watch?v=Za92Tz_g0zQ を写経したコード。VS2015RCでは動きませんでした!!gccとclangは動きます http://melpon.org/wandbox/permlink/NjTFeiy7I09uEipA http://melpon.org/wandbox/permlink/imId8rEPigdnqDgv
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 <initializer_list> | |
#include <iostream> | |
#include <string> | |
#include <tuple> | |
#include <type_traits> | |
#include <unordered_map> | |
#include <utility> | |
#include <vector> | |
template <typename F, typename... Args> | |
void for_each_argument(F&& f, Args&&... args) | |
{ | |
[](...) {}((f(std::forward<Args>(args)), 0)...); | |
} | |
template <typename F, typename... Args> | |
void for_args(F&& f, Args&&... args) | |
{ | |
return (void)std::initializer_list<int>{ | |
( | |
f(std::forward<Args>(args)), | |
0 | |
)... | |
}; | |
} | |
template <typename... Args> | |
auto make_vector(Args&&... args) | |
{ | |
using value_type = std::common_type_t<Args...>; | |
std::vector<value_type> result; | |
result.reserve(sizeof...(Args)); | |
for_args( | |
[&result](auto const& x) | |
{ | |
result.emplace_back(std::forward<decltype(x)>(x)); | |
}, | |
std::forward<Args>(args)... | |
); | |
return result; | |
} | |
template <typename F, typename Tuple, std::size_t... Is> | |
decltype(auto) apply_impl(F&& f, Tuple&& tuple, std::index_sequence<Is...>) | |
{ | |
return std::forward<F>(f)(std::get<Is>(std::forward<Tuple>(tuple))...); | |
} | |
template <typename F, typename Tuple> | |
decltype(auto) apply(F&& f, Tuple&& tuple) | |
{ | |
using indices | |
= std::make_index_sequence< | |
std::tuple_size<std::decay_t<Tuple>>::value | |
>; | |
return apply_impl(std::forward<F>(f), std::forward<Tuple>(tuple), indices{}); | |
} | |
template <typename F, typename Tuple> | |
void for_tuple(F&& f, Tuple&& tuple) | |
{ | |
apply( | |
[&f](auto&&... xs) | |
{ | |
for_args(f, std::forward<decltype(xs)>(xs)...); | |
}, | |
std::forward<Tuple>(tuple) | |
); | |
} | |
template <typename, typename> | |
struct for_nargs_impl; | |
template <std::size_t Arity, typename F, typename... Args> | |
void for_nargs(F&& f, Args&&... args) | |
{ | |
std::size_t constexpr number_of_args = sizeof...(Args); | |
static_assert(number_of_args % Arity == 0, "invalid number of arguments"); | |
for_nargs_impl< | |
std::make_index_sequence<number_of_args / Arity>, | |
std::make_index_sequence<Arity> | |
>::apply( | |
f, | |
std::forward_as_tuple(std::forward<Args>(args)...) | |
); | |
} | |
template <std::size_t... Calls, std::size_t... Arity> | |
struct for_nargs_impl< | |
std::index_sequence<Calls...>, | |
std::index_sequence<Arity...> | |
> | |
{ | |
template <typename F, typename... Args> | |
static void apply(F&& f, std::tuple<Args...> const& tuple) | |
{ | |
auto constexpr arity = sizeof...(Arity); | |
using swallow = bool[]; | |
(void) swallow | |
{ | |
(apply_n<Calls * arity>(std::forward<F>(f), tuple), true)... | |
}; | |
} | |
template <std::size_t Base, typename F, typename... Args> | |
static void apply_n(F&& f, std::tuple<Args...> const& tuple) | |
{ | |
f(std::get<Base + Arity>(tuple)...); | |
} | |
}; | |
template <typename... Args> | |
auto make_unordered_map(Args&&... args); | |
template <typename, typename...> | |
struct common_kv_helper; | |
template <std::size_t... Is, typename... Ts> | |
struct common_kv_helper< | |
std::index_sequence<Is...>, | |
Ts... | |
> | |
{ | |
static_assert(sizeof...(Ts) % 2 == 0, ""); | |
template <std::size_t N> | |
using type_at = typename std::tuple_element<N, std::tuple<Ts...>>::type; | |
using key_type = std::common_type_t<type_at<Is * 2>...>; | |
using value_type = std::common_type_t<type_at<Is * 2 + 1>...>; | |
}; | |
template <typename... Ts> | |
using helper_for = common_kv_helper< | |
std::make_index_sequence<sizeof...(Ts) / 2>, | |
Ts... | |
>; | |
template <typename... Ts> | |
using common_key_type = typename helper_for<Ts...>::key_type; | |
template <typename... Ts> | |
using common_value_type = typename helper_for<Ts...>::value_type; | |
static_assert(std::is_same<common_key_type<std::string, int>, std::string>::value, ""); | |
static_assert(std::is_same<common_value_type<std::string, int>, int>::value, ""); | |
template <typename... Args> | |
auto make_unordered_map(Args&&... args) | |
{ | |
using key_type = common_key_type<Args...>; | |
using value_type = common_value_type<Args...>; | |
std::unordered_map<key_type, value_type> result; | |
result.reserve(sizeof...(Args) / 2); | |
for_nargs<2>( | |
[&result](auto&& k, auto&& v) | |
{ | |
result.emplace(std::forward<decltype(k)>(k), std::forward<decltype(v)>(v)); | |
}, | |
std::forward<Args>(args)... | |
); | |
return result; | |
} | |
int main() | |
{ | |
for_args( | |
[](auto const& x) { std::cout << x; }, | |
"hello", | |
0, | |
1, | |
2 | |
); | |
std::cout << "\n"; | |
auto v = make_vector(1, 2, 3, 4, 5); | |
static_assert(std::is_same<decltype(v), std::vector<int>>::value, "vector"); | |
for (auto const& x : v) { | |
std::cout << x; | |
} | |
std::cout << "\n"; | |
for_tuple( | |
[](auto const& x) { std::cout << x << " "; }, | |
std::make_tuple(1, "hello", 15.f, 'c') | |
); | |
std::cout << "\n"; | |
for_nargs<2>( | |
[](auto const& x, auto const& y) { std::cout << x * y << " "; }, | |
2, 1, | |
2, 2, | |
2, 3, | |
2, 4 | |
); | |
std::cout << "\n"; | |
for_nargs<3>( | |
[](auto const& x, auto const& y, auto const& z) { std::cout << x + y + z << " "; }, | |
1, 1, 1, | |
2, 2, 2, | |
3, 3, 3, | |
4, 4, 4 | |
); | |
std::cout << "\n"; | |
auto m = make_unordered_map( | |
"zero", 0, | |
"one", 1, | |
"two", 2.f | |
); | |
static_assert(std::is_same< | |
decltype(m), | |
std::unordered_map<char const*, float> | |
>::value, ""); | |
std::cout << m["zero"] << m["one"] << m["two"]; | |
std::cout << "\n"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment