8

タプルの最後の要素を削除しようとしています。タプルに削除する要素が1つしかない場合に機能します。しかし、複数あると、うまくいきません。これが機能しない理由がわかりません。これらは私が得ているエラーです:

prog.cpp: 関数 '<code>int main()':
prog.cpp:24:22: エラー: 不完全な型 '<code>remove_last<std::tuple<int, int> >' がネストされた名前指定子で使用されています
prog.cpp:24:22: エラー: 不完全な型 '<code>remove_last<std::tuple<int, int> >' がネストされた名前指定子で使用されました
prog.cpp:24:70: エラー: テンプレート引数 1 が無効です

#include <tuple>
#include <type_traits>

template <class T>
struct remove_last;

template <class T>
struct remove_last<std::tuple<T>>
{
    using type = std::tuple<>;
};

template <class... Args, typename T>
struct remove_last<std::tuple<Args..., T>>
{
    using type = std::tuple<Args...>;
};

int main()
{
    std::tuple<int, int> var;

    static_assert(
        std::is_same<remove_last<decltype(var)>::type,
        std::tuple<int>>::value, "Values are not the same"
    );
}

特殊化の 1 つでテンプレート引数を非可変長にすると、エラーはなくなります。しかし、それは 2 つの要素を持つタプルのみを処理する特殊化になります。これは私が目指していたものではありません。これを可変引数で動作せるにはどうすればよいですか? 言い換えれば、タプルに複数の要素がある場合、どうすればこれを機能させることができますか?

4

2 に答える 2

6

問題は、引数 pack が貪欲であり、最初に来るため、型推論を実行するときに、Tから除外されると予想される を含め、シーケンス内のすべての型を使い果たすことですArgs...

可変個引数の特殊化を次のように定義できます (引数 pack がの最後に表示されていることに注意してくださいstd::tuple<T, Args...>)。

template <class T, class... Args>
struct remove_last<std::tuple<T, Args...>>
{
    using type = typename concat_tuple<
        std::tuple<T>,
        typename remove_last<std::tuple<Args...>>::type
        >::type;
};

そして、concat_tupleメタ関数を次のように定義します。

template<typename, typename>
struct concat_tuple { };

template<typename... Ts, typename... Us>
struct concat_tuple<std::tuple<Ts...>, std::tuple<Us...>>
{
    using type = std::tuple<Ts..., Us...>;
};
于 2013-04-28T21:48:11.560 に答える