二項演算子を前置する遊び
std::plus
#include <utility>
#include <tuple>namespace prefix_op {
namespace detail {
template<size_t N, typename T>
typename std::tuple_element<N, T>::type &
get_with_tuple_ref_collapsing(T & tup) {
return std::get<N>(tup);
}
template<size_t N, typename T>
typename std::tuple_element<N, T>::type &&
get_with_tuple_ref_collapsing(T && tup) {
return std::move(std::get<N>(tup));
}struct adder {
template<typename T, typename U>
auto operator()(T && t, U && u) const
->decltype(std::forward<T>(t) + std::forward<U>(u))
{
return std::forward<T>(t) + std::forward<U>(u);
}
};}
struct prefix_op_t {
detail::adder operator+(prefix_op_t) const {
return detail::adder();
}
template<typename T>
auto operator+(T && tup) const
->decltype(detail::get_with_tuple_ref_collapsing<0>(tup)
+ detail::get_with_tuple_ref_collapsing<1>(tup))
{
return detail::get_with_tuple_ref_collapsing<0>(tup)
+ detail::get_with_tuple_ref_collapsing<1>(tup);
}
template<typename T, typename U>
std::tuple<T &&, U &&> operator()(T && t, U && u) const {
return std::tuple<T &&, U &&>(std::forward<T>(t),
std::forward<U>(u));
}
} const _ = {};}
void f() {
using namespace prefix_op;_+_(1, 2);
_+_(1, _+_(2, 3));
1 + (_+_(2, 3));
1 + (_+_)(2, 3);
}
追記:template argument deductionの理解を間違えていたようなので、forward使ってるあたりを修正。