右辺値参照を使用して gcc で正常に動作する引数を格納するコールバック実装がありますが、一部のコードでは VS 2010 でコンパイルできません。短いバージョン:
#include <iostream>
#include <string>
class B {
public:
virtual void execute() = 0;
};
template<typename FuncType, typename ArgType>
class F : public B {
public:
F(FuncType func, ArgType && arg) : f(func), arg(arg) {}
void execute() { f(arg); }
private:
FuncType f;
ArgType && arg;
};
template<typename FuncType, typename ArgType>
B * registerFunc(FuncType func, ArgType && arg)
{
return new F<FuncType, ArgType>(func, arg);
}
void myFunction(std::string text)
{
std::cout << "Function " << text << " here" << std::endl;
}
int main()
{
const char text1[] = "sample1";
std::string text2("sample2");
B * b = registerFunc(myFunction, text1);
b->execute();
delete b;
b = registerFunc(myFunction, text2);
b->execute();
delete b;
// VS 2010 fails because of this call
b = registerFunc(myFunction, text2.c_str());
b->execute();
delete b;
return 0;
}
gcc 4.4 では、以下が生成されます。
$ g++ clbck.cpp -std=c++0x -o clbck && ./clbck
関数 sample1 はこちら
関数 sample2 はこちら
関数 sample2 はこちら
ただし、マークされた行のために registerFunc をインスタンス化しようとすると、VS 2010 でコンパイルに失敗します。
エラー C2664: 'F::F(FuncType,ArgType &&)' : パラメータ 2 を 'const char *' から 'const char *&&' に変換できません
[
FuncType
=void (__cdecl *)(std::string),
ArgType =const char *
]
左辺値を右辺値参照にバインドすることはできません
Googling は VS2010 の Boost 1.44 で同様のエラーを発見しましたが、推奨される解決策は右辺値参照をまったく使用しないことです。本当に他に方法はないのでしょうか?
そして、あなたがそれに取り組んでいる間、これらのコールバックを処理している方法に何か問題がありますか? 関数ポインターとファンクター (私はまだラムダをテストしていません) で問題なく動作します。私が見つけた唯一の欠点は、上記のものです。(ここに示されているコードは単なるデモであり、実際のコードではユーザーにポインターを提供していないことに注意してください。実際にこれを使用して、Qt アプリケーションのさまざまなスレッドで関数を実行しています)。