別の解決策は次のようになります。
#include <tuple>
#include <utility>
#include <functional>
#include <type_traits>
template <size_t N, class R, class Pack, class ResultPack, class Voider>
struct FuncTypeImpl;
template <size_t N, class R, template <class...> class Pack, class First, class... Args, class... ResultArgs>
struct FuncTypeImpl<N, R, Pack<First, Args...>, Pack<ResultArgs...>, std::enable_if_t<(N > 0)>>: FuncTypeImpl<N-1, R, Pack<Args...>, Pack<ResultArgs..., First>, void> {
using typename FuncTypeImpl<N-1, R, Pack<Args...>, Pack<ResultArgs..., First>, void>::Type;
};
template <size_t N, class R, template <class...> class Pack, class... Args, class... ResultArgs>
struct FuncTypeImpl<N, R, Pack<Args...>, Pack<ResultArgs...>, std::enable_if_t<(N == 0)>> {
using Type = std::function<R(ResultArgs...)>;
};
template<std::size_t, typename>
struct FuncType;
template<std::size_t N, typename R, typename... A>
struct FuncType<N, R(A...)> {
using Type = typename FuncTypeImpl<N, R, std::tuple<A...>, std::tuple<>, void>::Type;
};
int main() {
static_assert(
std::is_same<
FuncType<3, void(int, char, double, int)>::Type,
std::function<void(int, char, double)>
>::value,
"!"
);
}
編集: さらに別の(つまりはstd ::タプルを必要としない)多分少し簡単なソリューション:
#include <utility>
#include <functional>
#include <type_traits>
template <class T>
struct ResultOf;
template <class R, class... Args>
struct ResultOf<R(Args...)> {
using Type = R;
};
template<std::size_t N, class Foo, class ResultFoo = typename ResultOf<Foo>::Type() , class Voider = void>
struct FuncType;
template<std::size_t N, class R, class First, class... Args, class... ResultArgs >
struct FuncType<N, R(First, Args...), R(ResultArgs...), std::enable_if_t<(N > 0)>>: FuncType<N-1, R(Args...), R(ResultArgs..., First), void> {
};
template<std::size_t N, class R, class First, class... Args, class... ResultArgs >
struct FuncType<N, R(First, Args...), R(ResultArgs...), std::enable_if_t<(N == 0)>> {
using Type = std::function<R(ResultArgs...)>;
};
int main() {
static_assert(
std::is_same<
FuncType<3, void(int, char, double*, int)>::Type,
std::function<void(int, char, double*)>
>::value,
"!"
);
}
ニースQ&その解決策。コーディングの喜びのようです。しかし、私はこれが実際にどこで使われるのか分からないのですか?実際のアプリケーションで、なぜ単純な 'std :: function'の代わりに 'FuncType <2、void(int、char、double、int)> :: Type'を使用したいのですか?テンプレートの中でさえ、そのようなことをする必要はほとんどありません。厳しい問題を解決するには、2つの方法があります.1つの厳しい解決策を導き出すか、問題を簡単にするかのどちらかです。 :-) –
iammilind
@iammilindミックスインを使って何かをデザインしようとしたときに問題が発生しました。ミックスインの1つはバリデーショナルなタイプのリストを取得します。最後のタイプは継承するタイプのリストです。最初の 'N-1'は関数型の引数として使われなければならないことは言うまでもない。 :-) – skypjack