我想使用 C++ 17 结构化绑定(bind)为类成员变量赋值,如下所示:
#include <cmath>
#include <iostream>
struct Result {
double value;
bool error;
};
Result square_root(double input) { return {std::sqrt(input), input < 0}; }
struct Calculator {
double result_;
bool error_;
public:
void ComputeSquareRoot(double input) {
[ result_, error_ ] = square_root(input);
}
void DisplayResult() {
if (error_)
std::cout << "Cannot take the square root of a negative number.\n";
else
std::cout << "The square root is " << result_ << ".\n";
}
};
int main(int argc, char* argv[]) {
Calculator calc;
calc.ComputeSquareRoot(64);
calc.DisplayResult();
}
但此代码无法编译并出现以下错误(使用 clang 5.0):
> clang++ structured_bindings.cpp -std=c++17 -o structured_bindings
structured_bindings.cpp:20:7: error: 'result_' in capture list does not name a variable
[ result_, error_ ] = square_root(input);
^
structured_bindings.cpp:20:16: error: 'error_' in capture list does not name a variable
[ result_, error_ ] = square_root(input);
^
structured_bindings.cpp:20:25: error: expected body of lambda expression
[ result_, error_ ] = square_root(input);
^
3 errors generated.
lambda 捕获似乎有些困惑。当然这会起作用:
auto[result, error] = square_root(input);
result_ = result;
error_ = error;
但我想避免使用新的局部变量。结构化绑定(bind)是否可行?
最佳答案
使用std::tie
为现有对象赋值:
std::tie(result_, error_) = square_root(input);
这就是它被添加到 C++11 的原因。当然,您需要放弃使用 Result
而使用 std::tuple
。哪个 IMO 更适合这种临时的“返回多个东西”场景。
结构化绑定(bind)专用于声明新名称。
另一种可能更好的方法是不重新发明轮子,因为 C++1z 已经摆在桌面上了。返回一个 std::optional
auto square_root(double input) {
return input < 0 ? std::nullopt : std::optional{std::sqrt(input)};
}
这具有“可能有值,也可能没有”的明确语义。
顺便说一下,无条件地调用带有负输入的 std::sqrt
是个坏主意。特别是如果您事先没有以任何特殊方式配置浮点环境。
关于c++ - 是否可以使用结构化绑定(bind)来分配类成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47924527/