5

テンプレートを使用してC++で機能マップの実装を作成することにしました。これが、私が思いついたものです。

template <
    class U, 
    class V, 
    template <class> class T 
>

class T<V> WugMap(
    class T<U>::const_iterator first, 
    class T<U>::const_iterator second, 
    V (U::*method)() const)

{
    class T<V> collection;
    while (first != second)
    {
        collection.insert(collection.end(), ((*(first++)).*method)());
    }
    return collection;
}

今、これはすべてうまくてダンディであり、コンパイルさえします。問題は、実際にそれをどのように呼ぶのかわからないということです。

素朴な方法を試してみると、次のエラーが発生します。

prog.cpp:42: error: no matching function for call to 
‘WugMap(__gnu_cxx::__normal_iterator<Container*, std::vector<Container, 
std::allocator<Container> > >, __gnu_cxx::__normal_iterator<Container*, 
std::vector<Container, std::allocator<Container> > >, int (Container::*)()const)’

私の知る限り、すべての議論は正しい。gccは代替案をまったく提案していないので、私のWugMapの定義は疑わしいと思いますが、コンパイルは正常であるため、かなり迷っています。誰かがこの愚かさを通して私を導くことができますか?

誰かが、あらゆるタイプのオブジェクトを含むあらゆるタイプのコレクションの消費をサポートするこのような関数を作成するためのより良い方法を提案できる場合は、それを変更することを検討します。

これが私のこれまでのイデオネです。

現在、C ++ 03、gcc4.3.4を使用しているIdeoneを使用しています。

補遺1

これはC++11で可能ですか?そうだとほのめかされています。C ++ 11のテンプレートはさまざまな数の引数をサポートしていることを知っているので、それに合わせて要件を変更します。私は何かを書くことに少し努力しますが、それまでの間、私が探している要件は次のとおりです。

  • 次のような署名が必要です。

    C2<V, ...> map(const C1<U, ...>&, V (U::*)(...), ...)
    

    これは、参照により、いくつかのデフォルトパラメータで構築された、タイプUの要素を含むコレクションC1を取得し、Uのメンバー関数(Vを返し、未知のタイプのいくつかの引数を取得)を取得し、次に、順序、メンバー関数に渡される引数。この関数は最終的に、タイプVの要素を含み、不明な数のデフォルトパラメーターで初期化されているタイプC2のコレクションを返します。

  • チェーン可能である必要があります:

    vector<int> herp = map(
                       map(
                            set<Class1, myComparator>(),
                       &Class1::getClass2, 2, 3),
                       &Class2::getFoo);
    
  • テンプレート引数やその他の冗長性を使用する必要がない場合は、ボーナスポイントがあります。

std::transform素晴らしいですが、連鎖することはできません。

4

2 に答える 2

4

テンプレート引数は、ネストされた型から推測することはできません。Uとがメンバー関数ポインタから推測できる場合でもV、テンプレートタイプを推測することはできませんT

ideoneへのリンクのようにテンプレート引数を明示的に指定すること(上記のステートメントを書く前にリンクを作成しなかった)も機能しません。これは主に、のテンプレート引数std::vectorが単一の型ではないためTです。std::vector値型とアロケータ型を取ります。物事を修正することはかなり醜いです:

#include <vector>
#include <iostream>

using namespace std;

class Container
{
public:
    Container() {}
    Container(int _i) : i(_i) {}

    int get_i() const {return i;}

    int i;
};

    template <
        class U, 
        class V, 
        template <typename...> class T 
    >

    T<V> WugMap(
        typename T<U>::const_iterator first, 
        typename T<U>::const_iterator second, 
        V (U::*method)() const)
    {
        T<V> collection;
        while (first != second)
        {
            collection.insert(collection.end(), ((*(first++)).*method)());
        }
        return collection;
    }

int main()
{
    vector<Container> containers;
    for (int i = 0; i < 10; ++i) containers.push_back((Container(i)));

    WugMap<Container, int, std::vector>(
        containers.begin(), containers.end(), &Container::get_i);
}
于 2012-10-16T18:17:35.420 に答える
2

これが答えになるべきかどうかは本当にわかりませんが、一体:

std::vector<std::string> src = f();
std::vector<std::string::size_type> sizes; 
sizes.reserve(src.size());
// Actual transformation:
std::transform( src.begin(), src.end(), std::back_inserter(sizes), 
                [](std::string const& s) { return s.size(); } );

同様のことを手動で行うこともできますが、再発明されたホイールを再発明する意味はありません。

ケースの違いについては、std::transform型をそれほど緊密にバインドしようとはせずIter1、最初の2つの引数、Iter23番目の引数、および3番目の引数を取りますFunctorIter1Iter2が同じタイプのコンテナーへのイテレーターであること、またはFunctor最初のコンテナーの値型から2番目のコンテナーの値型に変換されることを保証するためのインターフェースのチェックはありません。

于 2012-10-16T18:53:23.213 に答える