0

ユーザー定義クラスで bind2nd を使用する方法を学習しようとしていますが、他のリソースを調べて支援を求めたにもかかわらず、修正方法がわからないというエラーが表示されます。

助けていただければ幸いです、ありがとう。

main.cpp

#include <algorithm>
#include <vector>

class F
{
public:
  int operator()(int a, int b)
  {
    return a * b;
  }
};

int main(void)
{
  std::vector<int> bases;

  for(int i = 0; i < 5; ++i)
    bases.push_back(i);

  std::transform(bases.begin(), bases.end(), bases.begin(), std::bind2nd(F(), 2));
  // Error C2664: '_OutIt std::transform<std::_Vector_iterator<_Myvec>,std::_Vector_iterator<_Myvec>,
  // std::binder2nd<_Fn2>>(_InIt,_InIt,_OutIt,_Fn1)' : cannot convert parameter 4 from
  // 'std::binder2nd<_Fn2>' to 'std::binder2nd<_Fn2>'
}
4

2 に答える 2

2

std::bindこれは、const参照をファンクター引数として取るため、constでなければならないことを指摘したStefanの回答を完了しoperator ()ます。

ここで、バイナリ ファンクターは に適応できる必要がありますstd::bind2ndbind2ndtypedef 、および. F_first_argument_typesecond_argument_typeresult_type

class F
{
public:
    typedef int first_argument_type;
    typedef int second_argument_type;
    typedef int result_type;

    int operator()(int a, int b) const
    {
        return a * b;
    }
};

C++11 ではstd::bind、これらの必要な typedef を持たない、より汎用的で柔軟なソリューションが導入されています

于 2013-07-21T20:40:02.293 に答える
2

まず、バインダー機能を使用するには機能を含める必要があります。

次に、operator() を const に指定する必要があります。

3 番目に、*first_argument_type* などの型特性情報を取得するには、std::binary_function から継承するのが最善です。

#include <algorithm>
#include <vector>
#include <functional>
#include <iterator>
#include <iostream>

struct F : public std::binary_function<int, int, int>
{
    int operator()(int a, int b) const
    {
        return a * b;
    }
};

int main(void)
{
    std::vector<int> bases;

    for(int i = 0; i < 5; ++i)
        bases.push_back(i);

    std::transform(bases.begin(), bases.end(), bases.begin(), std::bind2nd(F(), 2));

    // print it to stdout
    std::copy(bases.begin(), bases.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;
}

編集

C++11 対応のコンパイラと stdlib にアクセスできる場合は、ベクトル充填コードを次のように簡単に書き換えることができます。

std::vector<int> bases(5);
int i = 0;

std::generate(bases.begin(), bases.end(), [&i]() { return ++i; });

C++11 では、新しいバインダー (boost::bind から移動) std::bind があります。これははるかに柔軟であり、必要に応じて試してみてください。そのような:

using namespace std::placeholders;
std::transform(std::begin(bases), std::end(bases), std::begin(bases), 
               std::bind(F(), 2, _1));

(以下の回答から、a.lasram が新しい std::bind について言及していることがわかりました。プロジェクトなどで、代わりに新しい C++ 11 を使用することが許可されているかどうかはわかりません。古い C++03 の機能. もし私があなただったら、あなたが許可されていないなら、それなら (有名な Mr. Alexandrescu からの引用) "あなたのエージェントに電話してください." :) )

ところで。Ryan (コメントを参照) は、私の最も精巧な std::generate でさえ ;) を使用して短く書くことができると述べたとき、絶対に正しいですiota:

std::iota(bases.begin(), bases.end(), 1);

std::iota はnumericで定義されています。したがって、それも含める必要があります。

それが役立つことを願っています。

于 2013-07-21T20:38:22.557 に答える