私はmap_n
テンプレートを持っています。これは、N個の入力タプルから要素の各セットにN-arity関数を適用して新しい出力タプルを生成します。すべての入力タプルは同じ長さでなければなりません(静的なアサーションで確認する必要があります)。非形式引数のC++バリデーションテンプレート部分特殊化
次のコードスニペットに示すように、再帰終了条件の部分的な特殊化を一般的な方法で書くことができなかったことを除いて、コードは正しく動作します。
#include <tuple>
#include <cassert>
namespace impl {
// car, cdr, cons implementation
//
template<unsigned... XS>
struct sequence {
template<unsigned X>
using cons = sequence<X, XS...>;
};
template<unsigned start, unsigned end>
struct range {
static_assert(start < end, "Range: start > end");
using type = typename range<start + 1, end>::type::template cons<start>;
};
template<unsigned start>
struct range<start, start> {
using type = sequence<>;
};
template<typename T, unsigned... N>
auto select(const T& t, sequence<N...>) {
return std::make_tuple(std::get<N>(t)...);
}
} // end namespace impl
// car, cdr, cons
//
// empty list
//
constexpr const std::tuple<> empty;
// car
//
template<typename T>
auto car(const T& t) { return std::get<0>(t); }
// cdr
//
template<typename T, typename R = typename impl::range<1, std::tuple_size<T>::value>::type>
auto cdr(const T& t) {
return impl::select(t, R());
}
// cons
//
template<typename X, typename... XS>
auto cons(X x, const std::tuple<XS...>& t) {
return std::tuple_cat(std::make_tuple(x), t);
}
namespace impl {
// map_n implementation
template<typename F, typename... Ts>
struct map_n_impl {
static auto map(const F& f, const Ts&... t) {
return cons(
f(car(t)...),
map_n_impl<F, decltype(cdr(t))...>::map(f, cdr(t)...)
);
}
};
// NOTE: Need a more general specialization here
//
template<typename F>
struct map_n_impl<F, std::tuple<>, std::tuple<>> {
static std::tuple<> map(const F&, const std::tuple<>&, const std::tuple<>&)
{
return std::make_tuple();
}
};
} // end namespace impl
// map_n
//
template<typename F, typename... Ts>
auto map_n(const F& f, const Ts&... t) {
return impl::map_n_impl<F, Ts...>::map(f, t...);
}
int main(int, const char **) {
{
auto tup1 = std::make_tuple(1.0, 2.0, 3.0);
auto tup2 = std::make_tuple(0.0, 1.0, 2.0);
auto r = map_n([](auto x, auto y) { return x - y; }, tup1, tup2);
assert(std::get<0>(r) == 1.0);
assert(std::get<1>(r) == 1.0);
assert(std::get<2>(r) == 1.0);
}
// {
// auto tup1 = std::make_tuple(1.0, 2.0, 3.0);
// auto tup2 = std::make_tuple(0.0, 1.0, 2.0);
// auto tup3 = std::make_tuple(4.0, 5.0, 6.0);
// auto r = map_n([](auto x, auto y, auto z) { return x - y + z; }, tup1, tup2, tupe3);
// assert(std::get<0>(r) == 5.0);
// assert(std::get<1>(r) == 6.0);
// assert(std::get<2>(r) == 7.0);
// }
return 0;
}
's/decltype(idx):: value/idx /'です。 –
@ T.C。それが可能であることを認識していませんでした。クール。 – Barry