没有匹配的构造函数来初始化 MyClassName

No matching constructor for initialization of MyClassName

我有一个 class,在截取的代码中我粘贴了我认为有问题的部分。

class SubtreeExplorer : public AbstractTask {
 public:
  SubtreeExplorer(Threadpool& tp, SudokuBoard&& sudoku)
      : tp(tp), sudoku(std::move(sudoku)) {}

 ...

 private:
  Threadpool& tp;
  SudokuBoard sudoku;
 
  bool sudoku_backtracking_search(SudokuBoard& s) {
   ...
   while(...){
      ...
      // let another thread explore the subtree
      tp.submit(make_shared<SubtreeExplorer>(tp, SudokuBoard(sudoku)));
   }
  }
};

当我尝试编译它时出现错误:

/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:4325:5: error: static_assert failed due to requirement 'is_constructible<SubtreeExplorer,
      Threadpool &, SudokuBoard &>::value' "Can't construct object in make_shared"
    static_assert( is_constructible<_Tp, _Args...>::value, "Can't construct object in make_shared" );

我正在使用 VS Code,在 IDE 中没有突出显示任何错误。 问题可能是由 make_shared 引起的,但我无法弄清楚构造函数中的内容 ok 导致它的 SubtreeExplorer class。

Sudokuboard(sudoku) returns 一块新板,来自给定的板,几乎没有修改。我希望将这个新板移动到新的子树资源管理器中。

查看google,我写的构造函数应该把板子移进去了,但我仍然得到我写的编译错误,加上一长串难以阅读的注释:

/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:2259:9: note: in instantiation of function template specialization
      'std::__1::__compressed_pair_elem<SubtreeExplorer, 1, false>::__compressed_pair_elem<Threadpool &, SudokuBoard &, 0, 1>' requested here
        _Base2(__pc, _VSTD::move(__second_args),
        ^ /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:3672:16: note: in instantiation of function template specialization
      'std::__1::__compressed_pair<std::__1::allocator<SubtreeExplorer>, SubtreeExplorer>::__compressed_pair<std::__1::allocator<SubtreeExplorer> &,
      Threadpool &, SudokuBoard &>' requested here
            :  __data_(piecewise_construct, _VSTD::forward_as_tuple(__a),
               ^ /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:4331:26: note: in instantiation of function template specialization
      'std::__1::__shared_ptr_emplace<SubtreeExplorer, std::__1::allocator<SubtreeExplorer>
>::__shared_ptr_emplace<Threadpool &, SudokuBoard &>' requested
      here
    ::new(__hold2.get()) _CntrlBlk(__a2, _VSTD::forward<_Args>(__args)...);
                         ^ /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:4710:29: note: in instantiation of function template specialization
      'std::__1::shared_ptr<SubtreeExplorer>::make_shared<Threadpool &, SudokuBoard &>' requested here
    return shared_ptr<_Tp>::make_shared(_VSTD::forward<_Args>(__args)...);
                            ^ src/sudoku_parallel.cpp:119:13: note: in instantiation of function template specialization 'std::__1::make_shared<SubtreeExplorer, Threadpool &, SudokuBoard
      &>' requested here   tp.submit(make_shared<SubtreeExplorer>(tp, sudoku));
            ^ src/sudoku_parallel.cpp:41:3: note: candidate constructor not viable: no known conversion from 'SudokuBoard' to 'SudokuBoard &&' for 2nd argument   SubtreeExplorer(Threadpool& tp, SudokuBoard&& sudoku)   ^ src/sudoku_parallel.cpp:39:7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided class SubtreeExplorer : public AbstractTask {
      ^ src/sudoku_parallel.cpp:39:7: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided

这让我觉得我向构造函数传递了错误数量的参数,即使它有两个参数并且我传递了两个参数,一个线程池和一个数独板。

在主体中,SubtreeExplorer 的创建类似于 sudoku_backtracking_search 函数的主体:

int main() {
   ...
   SubokuBoard sudoku(filepath);
   tp.submit(make_shared<SubtreeExplorer>(tp, sudoku));
   ...
}

编辑: tp 是一个线程池,其提交方法具有以下签名:

bool submit(std::shared_ptr<AbstractTask> task);

AbstractTask class 如下:

struct AbstractTask {
  virtual ~AbstractTask() = default;
  virtual void run() = 0;
};

构造函数采用对 SudokuBoard 的右值引用,但您将其传递给左值。这就是您收到错误的原因;左值引用不能隐式转换为右值引用,因此调用失败。

您可以使用以下任一选项更正问题:

  1. 最好的选择是更改 SubtreeExplorer 构造函数以按值接受第二个参数,这允许调用者移动构造或复制构造它,具体取决于是否他们需要保留一份论证副本。您可以在需要时获得移动语义的好处,但副本仍然可以接受。

    (假设 SudokuBoard 类型有一个复制构造函数。)

      SubtreeExplorer(Threadpool& tp, SudokuBoard sudoku)
          : tp(tp), sudoku(std::move(sudoku)) {}
    
  2. 通过应用 std::move():

    将右值引用传递给命名变量
    SubokuBoard sudoku(filepath);
    tp.submit(make_shared<SubtreeExplorer>(tp, std::move(sudoku)));
    
  3. 完全删除命名变量并传递一个临时变量:

    tp.submit(make_shared<SubtreeExplorer>(tp, SudokuBoard{filepath}));
    

我建议实施选项 1,但是如果您不需要在此之后使用 sudoku 变量,那么 实施选项 2 或 3 =18=] 调用 -- 否则你将进行无意义的复制。