2011-05-15 16 views
2

私のVS2010は、このコードはコンパイルできない理由:使用のstd :: tr1を::バインド::一back

#include <functional> 
#include <vector> 
int main() 
{ 
    std::vector<int> vec; 
    std::bind(&std::vector<int>::push_back, std::ref(vec), 1)(); 
    return 0; 
} 
+1

ペースト状にしてくださいあなたが取得しているエラー。たとえ私たちが助けようとしていても、私たちは霊能者ではありません。 – ereOn

+0

私はこれに誤りを見ない。私はそのコードを実行し、それはうまく動作します。 tr1/functionalを必ず含めてください。 –

+0

VS2010ではコンパイルされず、ヘッダーはありません。ちょうどです。私は間違って何をしていますか? – magenta

答えて

3

これを試してみてください:push_backはローカル型にすることはできませんというC++ 03のノートで

struct push_back { 
    void 
    operator()(std::vector<int>& vector, int i) const 
    { 
     vector.push_back(i); 
    } 
}; 

// somewhere else: 
std::vector<int> vec; 
std::tr1::bind(push_back(), std::tr1::ref(vec), 1)(); 

を。 C++ 11では可能ですが、ラムダを使うのはもっと慣用的(完全に同等)です。

あなたの実装ではstd::vector<T>::push_backのオーバーロードが提供されるため、そのアドレスは曖昧さを排除する必要があります。これが起こった場合、コンパイラは適切なエラーメッセージを提供する必要があります。 すべての場合は、「可能ではありません」という意味を説明する必要があります。


点は、ヘルパーに 機能を使用しないことです。 - マゼンタ

なぜあなたはそれを質問に入れませんでしたか?私はあなたの心を読むことができません。

また、これを試すことができます:私は成功に保証されていないと信じて

std::vector<int> vec; 
void (std::vector<int>::*push_back)(int const&) = &std::vector<int>::push_back; 
std::tr1::bind(push_back(), std::tr1::ref(vec), 1)(); 

+2

このようなヘルパー関数を使用しないことがポイントです。 – magenta

+2

@magentaあなたの質問を修正してください。 –

0

をそれはpropablyこのよう洛必要があります。

std::vector<int> vec; 
std::tr1::bind(&std::vector<int>::push_back, std::tr1::ref(vec), _1)(1); 
+0

違いはありません。 – magenta

5

なぜあなたのためにこれがうまくいかないのか、より具体的にする必要があります。

#include <iostream> 
#include <tr1/functional> 
#include <vector> 

int main(int argc, char* argv[]) { 
    std::vector<int> vec; 
    std::tr1::bind(&std::vector<int>::push_back, std::tr1::ref(vec), 1)(); 
    std::cout << "vec.size = " << vec.size() << std::endl; 
    std::cout << "vec[0] = " << vec[0] << std::endl; 
    return 0; 
} 

$ gcc -o test -lstdc++ test.cpp && ./test 
vec.size = 1 
vec[0] = 1 

更新:リュックダントンは、ここでの問題が過負荷push_backあり、権利です。質問Are there boost::bind issues with VS2010 ?を参照してください。また、問題はpush_backに限定されず、Visual Studio 2010 and boost::bindを参照してください。

+0

コンパイルされません。そして、問題は#include にあるようです。私はVS2010を使用しており、そのようなヘッダはありません。 – magenta

+0

@magenta:VS2010はtr1ヘッダーを持っていないだけで、tr1以外のヘッダーに埋め込まれています。また、VS2010はすべての重要なtr1名を通常のstd名前空間にインポートするので、 ''を '' std :: bind'を 'tr1'なしで使用するだけです。 – Xeo

4

最終行は、ポータブル C++では実行しようとしていないことです。 std::vector<>::push_backは、少なくともlvaluesのオーバーロードとrvaluesのオーバーロードが必要であるため、C++ 11コンパイラでオーバーロードされることが保証されています。

C++ 11 FDISは、我々は、我々は以下のようなものをのアドレスを取っている過負荷を制御できることを教えてくれるで通常、オーバーロードされたメンバ関数のアドレスを取得する場合、§13.4/ 1

引数なしでオーバーロードされた関数名の使用は、関数、関数へのポインタ、またはオーバーロードセットの特定の関数のメンバ関数へのポインタに特定のコンテキストで解決されます。関数テンプレート名は、そのようなコンテキストでオーバーロードされた関数のセットを指定すると見なされます。 選択された機能は、そのタイプがコンテキストで必要とされるターゲットタイプの関数タイプと同一であるものです。 [注:つまり、関数がメンバであるクラスは、メンバ関数へのポインタ型と一致するときに無視されます。末端音符]ターゲットは

  • 初期化されたオブジェクトまたは参照、
  • 割り当ての左側、
  • 関数のパラメータ、
  • ユーザのパラメータとすることができます
  • 関数、演算子関数、または変換の戻り値
  • 明示的な型変換または
  • 非型テンプレートパラメータ。

オーバーロードされた関数名の前には、&演算子を付けることができます。オーバーロードされた関数名は、リストされている以外のコンテキストでは、引数なしでは使用できません。 [注:オーバーロードされた関数名を囲む括弧の冗長な集合は無視されます。 末端ノート]

問題は§17.6.5.5/ 2から来ている:

実装は、デフォルトで引数を追加することにより、クラス内で追加の非仮想メンバ関数のシグネチャを宣言してもよいです値をメンバ関数の署名に変換する。 したがって、C++標準ライブラリのクラスのメンバ関数のアドレスは、不特定の型を持ちます。

したがって、定義によって実装することにより、実装基づい除く不可知である、そのような表現のタイプとして、これまでの標準ライブラリのクラスのメンバ関数のアドレスを取得するポータブルではありません。

リュックダントンの提案回避策(具体的には、ラムダを使用して)私が推薦する何もである:

std::vector<int> vec; 
[&](){ vec.push_back(1); }(); 
+0

はい、私たちがC++ 0xを使用するならば、ラムダがおそらく最良の選択です。しかし、実際に私はVS2010が私のコードをコンパイルできなかったのは不思議でした。 – magenta

関連する問題