是否可以使用结构化绑定来分配类成员?

Jos*_*son 1 c++ c++17

我想使用C++ 17结构化绑定为类成员变量赋值,如下所示:

#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();
}
Run Code Online (Sandbox Code Playgroud)

但是这段代码无法编译,出现以下错误(使用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.
Run Code Online (Sandbox Code Playgroud)

lambda捕获似乎有些混乱.当然这会奏效:

auto[result, error] = square_root(input);
result_ = result;
error_ = error;
Run Code Online (Sandbox Code Playgroud)

但我想避免使用新的局部变量.结构化绑定有可能吗?

Sto*_*ica 6

用于std::tie为现有对象赋值:

std::tie(result_, error_) = square_root(input);
Run Code Online (Sandbox Code Playgroud)

这就是它被添加到C++ 11的原因.当然,你需要放弃使用Result赞成a std::tuple.对于这种特殊的"返回多个事物"场景,哪个IMO更好.

结构化绑定专门用于声明名称.

另一种方法,可能更好,因为C++ 1z在桌面上,是不重新发明轮子.回来一个std::optional

auto square_root(double input) {
   return input < 0 ? std::nullopt : std::optional{std::sqrt(input)}; 
}
Run Code Online (Sandbox Code Playgroud)

这有一个明确的语义,"可能有价值,有没有".


顺便说一句,无条件地std::sqrt使用负输入调用是一个坏主意.特别是如果您之前没有以任何特殊方式配置浮点环境.