lambda在初始化列表中返回

时间:2014-12-10 12:39:24

标签: c++ c++11 lambda initializer-list

让我们看一个现实生活中的例子:

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;
        }() } {
}

使用这种技术有什么缺点吗?这值得吗?我发现它的可读性稍差,但性能如何?

2 个答案:

答案 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)的情况。