である私の複雑な状況:適切に可変引数テンプレート関数内のラムダにCの文字列を渡す方法ここで
私は可変長テンプレートとラムダ使用して機能を持っています、特定のイベントを観察する上で
template<typename...Args>
void foo(Args...args) {
// the arguments are passed to the lambda
_func = [args...](){ do_sth(args...); };
}
をラムダ_func
が発射される。 私の問題は、私は渡された引数のいくつかは、彼らはこのように一時的なSTDの文字列を指すことができ、Cの文字列で、次のとおりです。
const char *pStr = __temp_std__string__.c_str();
私はfoo(pStr);
を呼び出し、_func
が呼び出されたときに、一時的な文字列がのpStrがあることを考えます指し示す、リリースされました。これを処理する一般的な方法が存在するかどうかを知りたいと思います。私はC++ 11を使用しています。
EDIT:あなたの多くは、STDを渡すために助言するよう
おそらく、私は、私の全体的な話を投稿する必要があります::代わりにC文字列の文字列を、私はそれから逃れることができない理由があります。
私はC++ 11をデプロイするcocos2d-xを使ってゲームを開発しています。私がしたいのは、プレイヤーが言語の好みを変更するときに、ラベルの自動ローカライゼーションをサポートするためのです(UIから選択された)。
私はファイルのカップルでテキストを保存して、それらの各々は、単一の言語のローカライズされたテキストが含まれている、彼らは次のような構造の下で、基本的には、次のとおりです。
{
"key1" : "_localized_text1_",
"key2" : "_localized_text2_",
...
}
アイデアは、イベントを観察することです(通知を通じて)言語の好みの変更に応じて、私はそれから言語を示すキーを取得し、適切なファイルからローカライズされたテキストをフェッチするようにします。ここで私は、オブジェクトクラスLabel
でそれを実装する方法の方法は次のとおりです。
class Label {
// this method would update the label's displayed text
void setString(const std::string& text);
// set a callback for changing language
void setOnLanguageChangeFunc(std::function<void(Notification*)> func);
// set a localised text, which would be updated on changing language
void setLocalizeString(const std::string& key);
};
コア機能setLocalizeString
(彼らは彼らの宣言から十分に直感的として、私は他の2つの方法の実装をスキップ)である:
void Label::setLocalizeString(const std::string& key) {
// the callback lambda
auto callback = [=](Notification *pNotification){
setString(LOCALIZED_STRING(key));
}
// assign the lambda
setOnLanguageChangeFunc(callback);
}
LOCALIZED_STRING
は、ローカライズされた文字列をキーでフェッチするマクロヘルパーです。ラムダcallback
は、ローカルメンバー変数Label
としてsetOnLanguageChangeFunc
に保存されます。
これは、ほとんどのケースで素晴らしい作品は、どのような状況が複雑になることは、ローカライズされたテキストに関与書式指定があり、例えば:
{
...
"keyN" : "%s eats %d cookies",
...
}
このような形式のプレースホルダは、コードに動的に渡されます。
StringKit
// formatStr = "Tom eats 5 cookies"
std::string formatStr = StringKit::stringWithFormat("%s eats %d cookies", "Tom", 5);
は、文字列の書式を設定するためのユーティリティであり、それは、に渡される可変長引数を受け付けます出力を得るために3210。今では、Cの文字列を渡す必要がある理由を知っていますが、std :: stringではなく、文字列をフォーマットするための基本的なメソッドのためです。
今、私はそれが可能な可変長引数を消化することができるようにLabel::setLocalizeString
を変更する必要があります。
template<typename... Args>
void setLocalizeString(const std::string& key, Args... args)
{
// the callback lambda
auto callback = [=](Notification *pNotification){
setString(StringKit::stringWithFormat(LOCALIZED_STRING(sKey), args...));
}
// assign the lambda
setOnLanguageChangeFunc(callback);
}
を、これはそのユースケースである:
// on changing language, the label would display "Tom eats 5 cookies"
pLabel->setLocalizeString("keyN", "Tom", 5);
この場合は、そのような魅力のように動作しますCの文字列引数はグローバルですが、一時的なstd :: stringから渡されるとき:
std::string tempStr = "Tom";
pLabel->setLocalizeString("keyN", tempStr.c_str(), 5);
Cの文字列 "Tom"は、指摘されたstd :: stringがなくなったので、ラムダコールバックの呼び出し時に値を失います。
タプルのもので遊んだり、ラムダの基本型のラッパークラスを取り込んだりするなど、いくつかの方法を試しましたが、いずれも問題を解決できませんでした。しかし、私はいくつかのトリッキーな解決策が存在すべきだと思います。
よくduh。 Cの文字列を使用しないでください。特に所有権が関与している場合。 – milleniumbug
秘密の成分: 'std :: string'と' [=] '。 – IInspectable
あなたはC++ 11が 'std :: string'を既にサポートしていることを知りたいと思うでしょう! – sehe