如何在构造函数的成员初始化列表中调用两个函数?

How can I call two functions in contructor's member initializer list?

我可以调用初始化列表中的函数吗?请看这段代码:

#include <string>
using namespace std;

class A {
 public:
  A(string path) : s(cfg.getRoot()) {  // before i call getRoot, i need to call cfg.readFile(path.c_str()), is there any methods? (readFile return void)
  }

  private:
   libconfig::Config cfg;
   const libconfig::Setting & s;  // const &, so initalizer list is the only chance for me to init it
}

你需要把它包装成一个函子,例如static 成员函数或 lambda (C++11 起):

A(string path) : s([this]() -> const libconfig::Setting & 
                   { cfg.readFile(path.c_str()); return cfg.getRoot(); }
                   () 
                  ) 
{}

您还可以使用逗号运算符(尽管对于 reader 这可能会或可能不会更难理解):

A(string path) : s((cfg.readFile(path.c_str()), cfg.getRoot())) {}

内置逗号运算符从左到右计算并丢弃左侧表达式的结果。请注意,双括号是必需的。否则它将被解析为 s 构造函数的两个函数参数。

如果 cfg.readFile(path.c_str()) 的 return 类型有重载的逗号运算符(但这种情况很少见),这将无法正常工作。在这种情况下,您需要将结果转换为 void 以丢弃 return 值:

A(string path) : s((static_cast<void>(cfg.readFile(path.c_str())), cfg.getRoot())) {}

已经给出了 lambda 方法。如果使用 decltype(auto):

可以避免重复 return 类型
A(string path) : s([this]()->decltype(auto){
    cfg.readFile(path.c_str());
    return cfg.getRoot();
}()) {}

这又是一个风格问题,无论您是否喜欢明确地给出 return 类型。

正如@songyuanyao 在下面的评论中指出的那样,如果您未指定 return 类型或适当的占位符,那么如果 cfg.getRoot return 是引用,您将遇到麻烦,因为默认的 lambda 类型是一个 auto 占位符,这将导致从引用构造一个临时对象,然后您将绑定到 s 并将立即再次销毁。