いいえ、パックは最後でなければなりません。
しかし、あなたはそれを偽造することができます。パックの最後のタイプが何であるかを検出できます。の場合はSomeSpecialType
、関数を実行できます。そうでない場合は、引数を転送して追加SomeSpecialType
して、再帰的に自分自身を呼び出すことができます。fromNum(5)
凝ったものにしたい場合は、SFINAE 手法を使用して、コンパイル時に (つまり、別のオーバーロードで) このチェックを行うことができます。しかし、「ランタイム」チェックは特定のオーバーロードで一定であるため、ほぼ確実に最適化され、SFINAE は軽々しく使用されるべきではないことを考えると、おそらく手間をかける価値はありません。
これは、必要な署名を提供しませんが、必要な動作を提供します。コメントで意図した署名を説明する必要があります。
タイプミスなどを削除すると、次のようになります。
// extract the last type in a pack. The last type in a pack with no elements is
// not a type:
template<typename... Ts>
struct last_type {};
template<typename T0>
struct last_type<T0> {
typedef T0 type;
};
template<typename T0, typename T1, typename... Ts>
struct last_type<T0, T1, Ts...>:last_type<T1, Ts...> {};
// using aliases, because typename spam sucks:
template<typename Ts...>
using LastType = typename last_type<Ts...>::type;
template<bool b, typename T=void>
using EnableIf = typename std::enable_if<b, T>::type;
template<typename T>
using Decay = typename std::decay<T>::type;
// the case where the last argument is SomeSpecialType:
template<
typename... Args,
typename=EnableIf<
std::is_same<
Decay<LastType<Args...>>,
SomeSpecialType
>::value
>
void func( Args&&... args ) {
// code
}
// the case where there is no SomeSpecialType last:
template<
typename... Args,
typename=EnableIf<
!std::is_same<
typename std::decay<LastType<Args...>>::type,
SomeSpecialType
>::value
>
void func( Args&&... args ) {
func( std::forward<Args>(args)..., std::move(static_cast<SomeSpecialType>(fromNum(5))) );
}
// the 0-arg case, because both of the above require that there be an actual
// last type:
void func() {
func( std::move(static_cast<SomeSpecialType>(fromNum(5))) );
}
またはそれによく似たもの。