|
#pragma once |
|
|
|
// Copyright plasma-effect 2015 |
|
// Distributed under the Boost Software License, Version 1.0. |
|
// (See http://www.boost.org/LICENSE_1_0.txt) |
|
|
|
#include<type_traits> |
|
#include<tuple> |
|
|
|
namespace plasma |
|
{ |
|
namespace lambda |
|
{ |
|
namespace detail//for projection_t |
|
{ |
|
constexpr int pow(int v, std::size_t p) |
|
{ |
|
return (p == 0 ? 1 : (p == 1 ? v : (p == 2 ? v*v : (p % 2 == 0 ? pow(pow(v, p / 2), 2) : p*pow(pow(v, p / 2), 2))))); |
|
} |
|
|
|
template<int I, int... Is>struct char_to_int_i |
|
{ |
|
static constexpr int run(int p) |
|
{ |
|
return I*p + char_to_int_i<Is...>::run(p / 10); |
|
} |
|
}; |
|
template<int I>struct char_to_int_i<I> |
|
{ |
|
static constexpr int run(int p) |
|
{ |
|
return I; |
|
} |
|
}; |
|
template<bool F, int I>struct projection_i |
|
{ |
|
static_assert(F, "projection_t error: few parameter"); |
|
template<class... Ts>static constexpr void* run(Ts&&...) |
|
{ |
|
return nullptr; |
|
} |
|
}; |
|
template<int I>struct projection_i<true, I> |
|
{ |
|
template<class T, class... Ts>static constexpr decltype(auto) run(T&&, Ts&&... vs) |
|
{ |
|
return projection_i<true, I - 1>::run(std::forward<Ts>(vs)...); |
|
} |
|
}; |
|
template<>struct projection_i<true, 0> |
|
{ |
|
template<class T, class... Ts>static constexpr decltype(auto) run(T&& v, Ts&&...) |
|
{ |
|
return std::forward<T>(v); |
|
} |
|
}; |
|
|
|
}//detail for projection_t |
|
template<int I>struct projection_t |
|
{ |
|
constexpr projection_t(){} |
|
constexpr projection_t(projection_t<I>const&){} |
|
constexpr projection_t(projection_t<I>&&){} |
|
~projection_t() = default; |
|
template<class... Ts>constexpr decltype(auto) operator()(Ts&&... vs)const |
|
{ |
|
return detail::projection_i<(I<sizeof...(Ts)), I>::run(std::forward<Ts>(vs)...); |
|
} |
|
}; |
|
|
|
template<char... Is>constexpr auto operator"" _proj() |
|
{ |
|
return projection_t<detail::char_to_int_i<(Is - '0')...>::run(detail::pow(10, sizeof...(Is)-1))>{}; |
|
} |
|
}//lambda |
|
}//plasma |