当不应调用该构造函数时,复制参数会调用已删除的构造函数
Copying parameter invokes deleted constructor when that constructor shouldn't be called
#include <memory>
template <typename T>
class Wrapper {
public:
Wrapper() = delete;
Wrapper(const Wrapper&) = delete;
Wrapper(Wrapper&&) = delete;
~Wrapper() = default;
Wrapper(const T&) = delete;
Wrapper(T&& in) : instance{std::move(in)} {}
T instance;
};
void foo(Wrapper<std::shared_ptr<int>>) {}
int main() {
auto ptr = std::make_shared<int>(1);
foo(std::move(ptr));
}
这在 C++17 中一直有效,所以我从未想过,但为什么这段代码会尝试在 C++14 中调用移动构造函数?它不应该在函数参数中就地构建吗?这似乎不是 c++17 的问题,但不是用 c++14 编译的。
我看到的唯一解决方法是将 foo
参数设置为右值,但是在不将 foo
中的参数设置为 C++ 中的右值的情况下,我能做些什么来使这项工作正常进行吗14?
我的第一个想法是临时构造函数必须是构造函数才能传递给函数,但更令人惊讶的是即使使用 -fno-elide-constructors
并取消删除移动构造函数和复制构造函数好像不叫!这是 gcc 和 clang 中的错误吗?
请参阅 https://wandbox.org/permlink/f6sa5Rm3NxZLy5P1 了解错误
看看奇怪的行为 https://wandbox.org/permlink/Kh6CG4OVbUAjvEZz
当您调用 foo(std::move(ptr));
时,您并没有给它一个 Wrapper<std::shared_ptr<int>>
。因此,编译器生成一个临时文件并使用它来构造 foo
的参数。现在,这可以被省略,我们可以直接构造一个 Wrapper<std::shared_ptr<int>>
但 move/copy 构造函数仍然需要可访问,即使它从未被调用。
对于 C++17,这不再发生。我们有 这意味着没有临时对象被具体化,而是直接构造参数。
#include <memory>
template <typename T>
class Wrapper {
public:
Wrapper() = delete;
Wrapper(const Wrapper&) = delete;
Wrapper(Wrapper&&) = delete;
~Wrapper() = default;
Wrapper(const T&) = delete;
Wrapper(T&& in) : instance{std::move(in)} {}
T instance;
};
void foo(Wrapper<std::shared_ptr<int>>) {}
int main() {
auto ptr = std::make_shared<int>(1);
foo(std::move(ptr));
}
这在 C++17 中一直有效,所以我从未想过,但为什么这段代码会尝试在 C++14 中调用移动构造函数?它不应该在函数参数中就地构建吗?这似乎不是 c++17 的问题,但不是用 c++14 编译的。
我看到的唯一解决方法是将 foo
参数设置为右值,但是在不将 foo
中的参数设置为 C++ 中的右值的情况下,我能做些什么来使这项工作正常进行吗14?
我的第一个想法是临时构造函数必须是构造函数才能传递给函数,但更令人惊讶的是即使使用 -fno-elide-constructors
并取消删除移动构造函数和复制构造函数好像不叫!这是 gcc 和 clang 中的错误吗?
请参阅 https://wandbox.org/permlink/f6sa5Rm3NxZLy5P1 了解错误 看看奇怪的行为 https://wandbox.org/permlink/Kh6CG4OVbUAjvEZz
当您调用 foo(std::move(ptr));
时,您并没有给它一个 Wrapper<std::shared_ptr<int>>
。因此,编译器生成一个临时文件并使用它来构造 foo
的参数。现在,这可以被省略,我们可以直接构造一个 Wrapper<std::shared_ptr<int>>
但 move/copy 构造函数仍然需要可访问,即使它从未被调用。
对于 C++17,这不再发生。我们有