get_last
パラメータ パックの最後の要素を抽出するWrite 。
それを呼び出しますf
。コールしf
ます。
例として、
template<typename T0>
auto get_last( T0&& t0 )->decltype(std::forward<T0>(t0))
{
return std::forward<T0>(t0);
}
template<typename T0, typename... Ts>
auto get_last( T0&& t0, Ts&&... ts )->decltype(get_last(std::forward<Ts>(ts)...))
{
return get_last(std::forward<Ts>(ts)...);
}
オーバーロードの解決を気にしない場合はget_last
、ファンクターのように呼び出して処理するだけで十分かもしれません。
template <typename...Args>
void call(const char *name, Args...&& args)
{
auto&& f = get_last(std::forward<Args>(args)...);
f(3);
}
次のステップは、有効なファンクターを最後に渡さない場合に一致しないようにするために、いくつかの SFINAEenable_if
マジックを実行することです。ただし、これはおそらくやり過ぎです。call
が機能するかどうかを検出するにf(3)
は、単純な特性クラスを使用します。
// trivial traits class:
template<typename T>
struct is_type:std::true_type {};
template<typename Functor, typename=void>
struct can_be_called_with_3:std::false_type {}
template<typename Functor>
struct can_be_called_with_3<Functor,
typename std::enable_if<
std::is_type< decltype(
std::declval<Functor>(3)
) >::value
>::type
>:std::true_type {}
これはかなりばかげています。渡された型の要件がより複雑な場合 (たとえば、引数を指定して呼び出す必要がある場合) は、より洗練された traits クラスを使用する必要があります。
次に、次のように拡張call
します。
template <typename...Args>
auto call(const char *name, Args...&& args)
-> typename std::enable_if<
can_be_called_with_3< decltype( get_last(std::forward<Args>(args)... ) ) >::value
>::type
{ /* body unchanged */ }
これはかなり鈍いです。