这里是我的复杂局面:如何正确传递C字符串到拉姆达一个可变参数模板函数内部
我有一个函数使用可变参数模板和lambda:
template<typename...Args>
void foo(Args...args) {
// the arguments are passed to the lambda
_func = [args...](){ do_sth(args...); };
}
在观察特定的事件中, lambda _func
将被解雇。 我的问题是,一些我传递的参数是C字符串,它们可以指向临时STD字符串是这样的:
const char *pStr = __temp_std__string__.c_str();
鉴于我打电话foo(pStr);
,当_func
被调用时,临时字符串PSTR是指向,已被释放。我想知道是否存在通用的方法来处理这个问题。我正在使用C++ 11。
编辑:
也许我应该张贴我的整个故事,正如你们许多人建议通过的std :: string代替C字符串,有我无法逃避它的理由。
我正在开发使用cocos2d-x的游戏,它部署C++ 11。我想要做的是支持当玩家更改他们的语言偏好(从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
是用键获取本地化字符串的宏助手;并且lambda callback
将被保存为Label
的本地成员变量setOnLanguageChangeFunc
。
这在大多数情况下,伟大的,是什么让复杂的情况是,有参与本地化的文本格式说明,例如:
{
...
"keyN" : "%s eats %d cookies",
...
}
这种格式的占位符在代码动态传递:
// formatStr = "Tom eats 5 cookies"
std::string formatStr = StringKit::stringWithFormat("%s eats %d cookies", "Tom", 5);
其中StringKit
是格式化的字符串的实用程序,它接受这将被传递到可变参数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”将失去调用lambda回调的值,因为指向的std :: string已经消失。
我已经尝试了几种方法,比如玩元组事物,或者在lambda中捕获基本类型的包装类,但是他们都不能解决问题。不过,我认为应该存在一些棘手的解决方案。
嗯。那么不要使用C字符串。特别是涉及所有权时。 – milleniumbug
秘密成分:'std :: string'和'[=]'。 – IInspectable
如果您知道C++ 11已经支持'std :: string'! – sehe