我一直在寻找一个设施来交换两个具有强大异常保证的物品。那是;让交换完全进行,或者在异常情况下使目标处于初始状态。当前标准中是否有任何内容允许这样做,我找不到任何东西,虽然看起来很容易写。
我在下面的内容是我为了试验我正在寻找的东西而放在一起的版本,但它是noexcept,这不仅仅是我要求的强大"保证。出现了强有力的保证"无法测试,但noexcept保证可以。
#include <iostream>
#include <type_traits>
// Guarantee to exchange l and r fully
// or (not compile) leave them in the initial state
template<typename T>
void strong_exchange(T & l, T &r) noexcept
{
using std::swap;
static_assert( noexcept( swap(l, r) ), "Types must be noexcept swappable");
swap(l, r);
}
struct X
{
X()
{
throw "fish";
}
X(X &&) = delete;
};
int main(void)
{
int a, b;
strong_exchange(a, b);
X i, j;
strong_exchange(i, j);
}
答案 0 :(得分:1)
可能不可能:
如果复制分配不是noexcept
(或执行复制的其他方式),则不可能。如果它是noexcept
,std::swap()
应该做的事情。否则,可能没有什么可以做的。
答案 1 :(得分:0)
@Incomputable突出了这个问题,但我要提供完整性的答案。
#include <iostream> #include <type_traits> // Guarantee to exchange l and r fully or not compile. template<typename T> void noexcept_swap(T & l, T &r) noexcept { using std::swap; static_assert( noexcept( swap(l, r) ), "Types must be noexcept swappable"); swap(l, r); } // Guarantee to full assign r to l or not compile. template<typename T> void noexcept_assign(T & l, T r) noexcept { noexcept_swap(l, r); } struct Exchangeable { Exchangeable() { } // C++ std::swap requires these two for now thorw, so noexcept_swap will also need them Exchangeable(Exchangeable &&) noexcept { } Exchangeable & operator=(Exchangeable &&) noexcept { } // for noexcept_assign these is also required, since a copy is made durring assignment Exchangeable(Exchangeable &) noexcept { } Exchangeable & operator=(const Exchangeable &) noexcept { } }; // This class is the same as the above, but it does not have // a noexcept guarantee on the methods struct NotExchangeable { NotExchangeable() {} NotExchangeable(NotExchangeable &&) {} NotExchangeable & operator=(NotExchangeable &&) { } NotExchangeable(const NotExchangeable &) { } NotExchangeable & operator=(const NotExchangeable &) { } }; int main(void) { int a, b; noexcept_swap(a, b); // OK noexcept_assign(a, b); // OK Exchangeable i, j; i = j; // Might throw and fail to do a full copy. Depends. noexcept_swap(i, j); // OK noexcept_assign(i, j); // OK NotExchangeable x, y; #if 0 noexcept_swap(x, y); // Fails to compile and emits assertion noexcept_assign(x, y); // Fails to compile and emits assertion #endif }