我可以强制默认的特殊成员函数为 noexexcept 吗?
Can I force a default special member function to be noexcept?
以下结构无法在 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
. 另请参阅此问题。
我相信这已在 C++14 中修复(请参阅库缺陷 2103)。
我的问题是,有没有办法让我强制noexcept
默认移动分配运算符而无需自己定义它?
如果这是不可能的,有没有办法欺骗std::vector<int>
noexcept
移动可分配,以便noexcept(true)
传递到我的结构中?
我相信这已在 C++14 中修复(请参阅库缺陷 2103)。
作为DR,该修复应被视为对C++11的更正,因此某些C++11实现已经修复了它。
我的问题是,有没有办法让我强制
noexcept
默认的移动分配分配运算符,而无需自己定义它?
要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
其他分配器类型。
我不认为你可以强迫任何东西,但你可以包装它:
#include <iostream>
#include <vector>
template <typename T>
struct Wrap
{
public:
Wrap() noexcept
{
new (m_value) T;
}
Wrap(const Wrap& other) noexcept
{
new (m_value) T(std::move(other.value()));
}
Wrap(Wrap&& other) noexcept
{
std::swap(value(), other.value());
}
Wrap(const T& other) noexcept
{
new (m_value) T(std::move(other));
}
Wrap(T&& other) noexcept
{
new (m_value) T(std::move(other));
}
~Wrap() noexcept
{
value().~T();
}
Wrap& operator = (const Wrap& other) noexcept
{
value() = other.value();
return *this;
}
Wrap& operator = (Wrap&& other) noexcept
{
value() = std::move(other.value());
return *this;
}
Wrap& operator = (const T& other) noexcept
{
value() = other;
return *this;
}
Wrap& operator = (T&& other) noexcept
{
value() = std::move(other);
return *this;
}
T& value() noexcept { return *reinterpret_cast<T*>(m_value); }
const T& value() const noexcept { return *reinterpret_cast<const T*>(m_value); }
operator T& () noexcept { return value(); }
operator const T& () const noexcept { return value(); }
private:
typename std::aligned_storage <sizeof(T), std::alignment_of<T>::value>::type m_value[1];
};
struct Foo
{
public:
Foo& operator = (Foo&&) noexcept = default;
std::vector<int>& data() noexcept { return m_data; }
const std::vector<int>& data() const noexcept { return m_data; }
private:
Wrap<std::vector<int>> m_data;
};
int main() {
Foo foo;
foo.data().push_back(1);
Foo boo;
boo = std::move(foo);
// 01
std::cout << foo.data().size() << boo.data().size() << std::endl;
return 0;
}
(感谢乔纳森·韦克利)
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 我应该声明所有不抛出 noexexcept 的成员/函数吗?
- GCC/GCOV 为 使用 throw() / noexexcept 函数生成的不同分支覆盖
- 我可以强制默认的特殊成员函数为 noexexcept 吗?
- 将已删除的函数声明为 noexexcept 有什么意义吗?