9

私は C++0x を試していますが、発生した次の問題を解決する方法を考えていました。私は可変個引数テンプレートクラスを持っています:

template<typename... T>
class MyLovelyClass {

 template<typename SomeType>
 void DoSthWithStorageOfSomeType();

 private:
  std::tuple<std::vector<T>...> m_storage;
};

そこにある関数は、 SomeType テンプレート引数に対応する m_storage タプルのベクトルに対して何らかの操作を行うと想定されています (そうでない場合はコンパイル時に失敗します)。どうすればこれを行うことができますか?

私の考えは、パラメーターパックで SomeType のインデックスを見つけてから、 std::get を使用して適切なベクターを取得することでしたが、最初の部分を行う方法がわかりません。

4

3 に答える 3

7

タプルが最初に検出したタイプUを線形検索し、Uが見つからない場合はコンパイル時エラーが発生するコードを次に示します。タプルに複数のUが含まれている場合は、最初のタイプのみが検出されます。それがあなたが望む方針であるかどうかわからない。コンパイル時のインデックスを最初のUのタプルに返します。おそらく、それをのインデックスとして使用できますstd::get

免責事項:この答えのために一緒に投げられます。軽くテストされただけです。空のタプルなどのエッジケースには、改善できる厄介なエラーメッセージがあります。等

#include <type_traits>
#include <tuple>

template <class Tuple, class T, std::size_t Index = 0>
struct find_first;

template <std::size_t Index, bool Valid>
struct find_first_final_test
    : public std::integral_constant<std::size_t, Index>
{
};

template <std::size_t Index>
struct find_first_final_test<Index, false>
{
    static_assert(Index == -1, "Type not found in find_first");
};

template <class Head, class T, std::size_t Index>
struct find_first<std::tuple<Head>, T, Index>
    : public find_first_final_test<Index, std::is_same<Head, T>::value>
{
};

template <class Head, class ...Rest, class T, std::size_t Index>
struct find_first<std::tuple<Head, Rest...>, T, Index>
    : public std::conditional<std::is_same<Head, T>::value,
                    std::integral_constant<std::size_t, Index>,
                    find_first<std::tuple<Rest...>, T, Index+1>>::type
{
};

#include <iostream>

int main()
{
    typedef std::tuple<char, int, short> T;
    std::cout << find_first<T, double>::value << '\n';
}
于 2011-05-17T14:48:55.733 に答える
2

C++14 ソリューション:

template <typename T, typename U=void, typename... Types>
constexpr size_t index() {
    return std::is_same<T, U>::value ? 0 : 1 + index<T, Types...>();
}

使用する:

cout << index<A, Args...>() << "\n";
于 2014-12-25T21:48:10.377 に答える
1

SIZE_MAX を返すことで、「タイプが見つからない」ケースのサポートを Elazar のソリューションに追加しました。

template <class T, class F = void, class ...R>
constexpr size_t TypeIndex() {
    return is_same<T,F>::value
         ? 0
         : is_same<F,void>::value || TypeIndex<T,R...>() == SIZE_MAX
         ? SIZE_MAX
         : TypeIndex<T,R...>() + 1;
}

編集:「見つからない」インデックス値としてパラメーター パックのサイズを使用するように切り替えました。これは、「終わりを過ぎた 1 つ」のインデックスまたはイテレータの STL の使用法に似ており、より洗練されたソリューションになります。

template <class T, class F = void, class ...R>
constexpr size_t TypeIndex() {
    return is_same<T,F>::value || is_same<F,void>::value ? 0 : TypeIndex<T,R...>() + 1;
}
于 2015-01-08T20:48:38.947 に答える