17

push_back演算子をサポートするベクターやその他の型にいくつかの要素をプッシュするテンプレートを作成したいと思います。

私はこのようにそれを行うことができます

template<typename T>
T fill(size_t n) {
    T v;
    //(1)
    for(size_t i = 0; i < n; ++i){
        v.push_back(generate_some_how());
    }
    return v;
}

できます。しかし今は、v.reserve(n);代わりに(1). しかし、コンパイルされない型に対してこのコードをコンパイルできるようにしたいreserve

これを達成する簡単な方法はありますか?

ハードコーディングされた型を専門化するかもしれないことは知っていますが、それは良くないようです。

C++11 は問題ありません。

4

3 に答える 3

11

C ++ 11を使用した簡単な例:

template<class T>
auto maybe_reserve(T& v, size_t n, int)
    -> decltype(v.reserve(n), void())
{
  v.reserve(n);
}

template<class T>
void maybe_reserve(T&, size_t, long){}

template<typename T>
T fill(std::size_t n) {
    T v;
    maybe_reserve(v, n, 0);
    for(size_t i = 0; i < n; ++i){
        v.push_back(generate_some_how());
    }
    return v;
}

実例。説明については、こちらをご覧ください。

于 2013-03-08T20:18:12.293 に答える
6

C++11 で可能なアプローチ:

template<typename T, typename = void>
struct reserve_helper
{ static void call(T& obj, std::size_t s) { } };

template<typename T>
struct reserve_helper<T, decltype(std::declval<T>().reserve(0), void(0))>
{ static void call(T& obj, std::size_t s) { obj.reserve(s); } };

template<typename T>
T fill(std::size_t n)
{
    T v;
    reserve_helper<T>::call(v, 10);
    for(std::size_t i = 0; i < n; ++i){
        v.push_back(generate_somehow());
    }

    return v;
}

これは、メンバー関数を定義しない UDT でへの呼び出しが単純にスキップされることを示す実際の例です。reserve()reserve()

于 2013-03-08T20:20:26.907 に答える
2

難しいことではありません....予約メンバー関数の存在を正しい署名で検出する特性を記述する必要があります。そのツールをベルトに使用すると、さまざまなアプローチがあります。その特性を使用して呼び出しまたは no-opreserve_にディスパッチしてから呼び出すテンプレート関数を作成するか、ヘルパーまたはそれ自体で SFINAE を使用できます。fill のほとんどのコードは同じであるため、ヘルパー関数を使用してみます。reserve()// (1)fill

void reserve(std::size_t)C++03 にメンバー関数が存在するかどうかを検出します。

template <typename T>
struct has_reserve {
   typedef char yes;
   typedef yes  no[2];
   template <typename U, U> struct ptrmbr_to_type;
   template <typename U> 
   static yes& test(ptrmbr_to_type<void (T::*)(std::size_t),&U::reserve>*);
   template <typename U> static no& test(...);
   static const bool value = sizeof(test<T>(0))==sizeof(yes);
};
于 2013-03-08T20:09:12.057 に答える