派生模板类找不到基模板类的移动构造函数

seg*_*ult 0 c++ inheritance templates c++17

我有一个相当大的类,它被减少到下面的最小失败示例:

#include <vector>

template <typename T> class Base {
public:
  Base(std::vector<T> &&other) : map{other} {}

private:
  const std::vector<T> map;
};

template <typename T> class Derived : public Base<T> {
public:
  Derived(std::vector<T> &&other) : Base<T>{other} {}
};

int main() {
  Derived<double>(std::vector<double>{1,2,3});
}
Run Code Online (Sandbox Code Playgroud)

当我运行这个时,我得到

$ clang++ -std=c++17 -O3 main.cpp && ./a.out
main.cpp:13:37: error: no matching constructor for initialization of 'Base<double>'
  Derived(std::vector<T> &&other) : Base<T>{other} {}
                                    ^      ~~~~~~~
main.cpp:17:3: note: in instantiation of member function 'Derived<double>::Derived' requested here
  Derived<double>(std::vector<double>{1,2,3});
  ^
main.cpp:3:29: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'std::vector<double>' to 'const Base<double>' for 1st argument
template <typename T> class Base {
                            ^
main.cpp:3:29: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'std::vector<double>' to 'Base<double>' for 1st argument
template <typename T> class Base {
                            ^
main.cpp:5:3: note: candidate constructor not viable: no known conversion from 'std::vector<double>' to 'std::vector<double> &&' for 1st argument
  Base(std::vector<T> &&other) : map{other} {}
  ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

我不明白为什么这会给我一个编译错误。我希望Base<T>{other}在第 13 行调用第 5 行的构造函数,因为我传入的other是 inDerived的构造函数参数中声明为右值 ( std::vector<T> && other)的构造函数。但是,编译器说它是一个左值 ( std::vector<double>)。

Jon*_*ves 6

因为我传入了在 Derived 的构造函数参数中声明为右值的 other (std::vector && other)

实际上,在 的范围内Derived(std::vector<T> &&other)other是一个左值,其类型是右值引用。这是一个常见的混淆点。看看强大的cppreference

以下表达式是左值表达式:

  • 变量、函数、模板参数对象(C++20 起)或数据成员的名称,无论类型如何,例如 std::cin 或 std::endl。即使变量的类型是 rvalue reference,由其名称组成的表达式也是一个左值表达式;

您需要other通过std::move()inDerived的构造函数显式转换为右值:

template <typename T> class Derived : public Base<T> {
public:
  Derived(std::vector<T> &&other) : Base<T>{std::move(other)} {}
};
Run Code Online (Sandbox Code Playgroud)