让我们看一个现实生活中的例子:
class RuleNameConverter {
public:
RuleNameConverter(const boost::property_tree::ptree& pt);
int toIdentifier(const std::string& name) const;
std::string toName(const int id) const;
private:
using Bimap = boost::bimap<std::string, int>;
Bimap bimap_;
};
构造函数是这样的:
RuleNameConverter::RuleNameConverter(const boost::property_tree::ptree& pt) {
for (const auto& item : pt) {
if (item.first == "rule") {
auto name = item.second.get < std::string > ("<xmlattr>.name");
auto id = item.second.get<int>("<xmlattr>.id");
bimap_.insert(Bimap::value_type { name, id });
}
}
}
假设您需要 const 成员属性:
...
const Bimap bimap_;
};
您必须在初始化列表中初始化它,而不是在构造函数体中初始化它。它的初始化非常简单,因此您必须委派一个函数来计算其值。你可以使用lambda返回的值,利用移动语义(没有临时对象的副本):
RuleNameConverter::RuleNameConverter(const boost::property_tree::ptree& pt) :
bimap_ { [&pt]() {
Bimap results;
for (const auto& item : pt) {
if (item.first == "rule") {
auto name = item.second.get < std::string > ("<xmlattr>.name");
auto id = item.second.get<int>("<xmlattr>.id");
results.insert(Bimap::value_type {name, id});
}
}
return results;
}() } {
}
使用这种技术有什么缺点吗?这值得吗?我发现它的可读性稍差,但性能如何?
答案 0 :(得分:2)
在性能方面,它不应该那么重要。你不要复制任何Bitmap
个对象,你的lambda的构造不应该花费任何明显的时间。
但为了便于阅读,我将在这里创建一个静态成员函数而不是lambda:
class RuleNameConverter {
public:
RuleNameConverter(const boost::property_tree::ptree& pt);
private:
static Bitmap createBitmap(const boost::property_tree::ptree& pt);
};
RuleNameConverter::RuleNameConverter(const boost::property_tree::ptree& pt) :
bimap_ { createBitmap(pt) } {
}
Bitmap RuleNameConverter::createBitmap(const boost::property_tree::ptree& pt) {
Bimap results;
for (const auto& item : pt) {
if (item.first == "rule") {
auto name = item.second.get < std::string > ("<xmlattr>.name");
auto id = item.second.get<int>("<xmlattr>.id");
results.insert(Bimap::value_type {name, id});
}
}
return results;
}
当您需要使用辅助函数初始化多个成员时,为每个成员创建一个新的lambda会导致构造函数初始化列表中无法维护的混乱,但是几个辅助函数不需要具有该问题。此外,如果添加构造函数重载,则可以从多个构造函数轻松调用createBitmap
。
或者,如果createBitmap
的正文并非真正针对您的RuleNameConverter
,请使用常规的非会员功能。
答案 1 :(得分:1)
你可以将Bimap
包装在另一个类中,其构造函数与lambda具有完全相同的主体。
我无法看到如何在这种情况下使用lambda避免表面类会导致任何问题,除非它的意图可能不那么明确,因为它没有名字(但是&# 39;几乎是任何 lambda)的情况。