是否可以使用结构化绑定来分配类成员? [英] Is it possible to use structured bindings to assign class members?
问题描述
我想使用C ++ 17结构化绑定为类成员变量分配一个值,如下所示:
I'd like to use C++ 17 structured bindings to assign a value to a class member variable, like this:
#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):
But this code fails to compile with the following error (using 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捕获似乎有些混乱。肯定可以用:
There seems to be some confusion with lambda capture. Certainly this will work:
auto[result, error] = square_root(input);
result_ = result;
error_ = error;
但我想避免使用新的局部变量。
But I would like to avoid the need to use new local variables. Is this possible with structured bindings?
推荐答案
使用 std :: tie
为现有对象分配值:
Use std::tie
to assign values to existing objects:
std::tie(result_, error_) = square_root(input);
这就是为什么将其添加到C ++ 11中的原因。当然,您需要放弃使用 Result
来代替 std :: tuple
。
That's why it was added to C++11. Of course, you'd need to forego using Result
in favor of a std::tuple
. Which IMO is better for such ad-hoc "return multiple things" scenarios.
结构化绑定专门用于声明新名称。
Structured bindings are exclusively for declaring new names.
另一种方法可能是更好的方法,因为C ++ 1z已经面世了,它可能会更好,因为C ++ 1z已经面世。返回 std :: optional
Another approach, which could be even better, since C++1z is on the table, is to not re-invent the wheel. Return a std::optional
auto square_root(double input) {
return input < 0 ? std::nullopt : std::optional{std::sqrt(input)};
}
这具有可能有值或没有值的明确语义。 。
This has the clear semantics of "there may be a value, or not".
顺便说一句,无条件调用 std :: sqrt
输入为负是个坏主意。尤其是如果您之前没有以任何特殊方式配置浮点环境。
By the way, unconditionally calling std::sqrt
with a negative input is a bad idea. Especially if you don't configure your floating point environment in any special way prior.
这篇关于是否可以使用结构化绑定来分配类成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!