Let's see a real life example:
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_;
};
Where the constructor is this:
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 });
}
}
}
Assume you want a const member attribute:
...
const Bimap bimap_;
};
You must initialize it in the initializer list, not in the constructor body. It's initialization is non trivial, so you must delegate a function to compute its value. You can use the value returned by a lambda, taking advantages of the move semantics (no copy of temporary objects):
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;
}() } {
}
Are there any drawbacks to using this technique? Is it worth the trouble? I find it slightly less readable, but what about performance?
return results;
toreturn std::move(results);
. Yes, compilers have RVO, but this way is move verbose. - GreenScapereturn std::move(results);
. - user743382return results;
? - GreenScape