Skip to content

Instantly share code, notes, and snippets.

@nekko1119
Last active October 20, 2015 07:26
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 nekko1119/4c9065dec12f1d6d639b to your computer and use it in GitHub Desktop.
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
#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