以下结构无法在 C++11 下编译,因为我已将移动赋值运算符声明为 noexcept
。 :
struct foo
{
std::vector<int> data;
foo& operator=(foo&&) noexcept = default;
};
编译器生成的默认移动赋值运算符是noexcept(false)
因为 std::vector<int>
的移动分配也是 noexcept(false)
.这反过来是由于默认分配器具有 std::allocator_traits<T>:: propagate_on_container_move_assignment
的事实。设置为 std::false_type
.另见 this question .
我相信这已在 C++14 中得到修复(参见 library defect 2103)。
我的问题是,有没有办法让我强制noexcept
在默认移动赋值赋值运算符上,而不必自己定义它?
如果这不可能,有什么方法可以欺骗 std::vector<int>
成为noexcept
移动可分配的以便 noexcept(true)
传递到我的结构?
最佳答案
I believe this has been fixed in C++14 (see library defect 2103).
作为 DR,修复应该被视为对 C++11 的更正,因此一些 C++11 实现将已经修复它。
My question is, is there a way for me to force
noexcept
upon the default move assignment assignment operator without having to define it myself?
要使默认的移动赋值运算符为 noexcept
,您需要使其子对象具有 noexcept
移动赋值运算符。
我能想到的最明显的可移植方式是在 std::vector
周围使用包装器,它强制移动为 noexcept
template<typename T, typename A = std::allocator<T>>
struct Vector : std::vector<T, A>
{
using vector::vector;
Vector& operator=(Vector&& v) noexcept
{
static_cast<std::vector<T,A>&>(*this) = std::move(v);
return *this;
}
Vector& operator=(const Vector&) = default;
};
另一个类似的选项是使用 DR 2013 修复定义您自己的分配器类型并使用它:
template<typename T>
struct Allocator : std::allocator<T>
{
Allocator() = default;
template<typename U> Allocator(const Allocator<U>&) { }
using propagate_on_container_move_assignment = true_type;
template<typename U> struct rebind { using other = Allocator<U>; };
};
template<typename T>
using Vector = std::vector<T, Allocator<T>>;
另一种选择是使用标准库实现,例如 GCC,它实现了 DR 2013 的决议,并且还使 std::vector
的移动赋值运算符 noexcept
用于其他分配器类型,当已知所有分配器实例比较相等时。
关于c++ - 我可以强制默认特殊成员函数为 noexcept 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18730969/