在某些实施过程中,我遇到了关于异常安全保障和使用std::move()
的问题。我知道这不是一个问“你的意见是什么”(课堂模板Boo
)这个问题的好地方,但在这里我想确定我的理解是否正确并且在你读完这个问题之后也许你可以指引我走正确的道路。
请考虑以下代码:
struct Foo {
using Y = std::vector<std::string>;
using X = std::vector<Y>;
void add (Y y) {
src.push_back (std::move (y)); // (1)
src = process (std::move (src)); // (2)
}
private:
X process (X&& vec) { // (F)
for (auto& v : vec) {
v.resize (10); // (3)
}
return std::move (vec);
}
X src;
};
如果有异常,请查看add()
成员函数
从(1)并根据n4296 [vector.modifiers / 1]
如果在末尾插入单个元素时抛出异常且
T
为CopyInsertable
或is_nothrow_move_constructible<T>::value
为true
,则无效。
然后保留强有力的保证,我是对的吗?
如果我们查看(2),那么也可以抛出异常,因为(3)可以抛出异常。如果我错了,请纠正我:
在这种情况下(2)如果我将src
移动到process()
成员函数并从process()
抛出异常,那么src
是
未指定,这意味着只保留基本保证?
要使add()
成员函数强有力保证,我应该改变
(2)和(F)分别为:
src = process (src); // (2)
X process (X vec); // (F)
因此,如果Foo::src
拥有大量元素,那么强大
保证与效率较低有关(因为必须额外复制)?
也许保证级别应由该类用户决定,使其成为类模板,类似于:
struct S {};
struct B {};
template <typename T>
struct Boo {
using Y = std::vector<std::string>;
using X = std::vector<Y>;
void add (Y y) {
src.push_back (std::move (y));
src = process_helper (typename std::is_same<T, S>::type {});
}
private:
X process_helper (std::true_type) {
return process (src);
}
X process_helper (std::false_type) {
return process (std::move (src));
}
X process (X vec) {
for (auto& v : vec) {
v.resize (10);
}
return std::move (vec);
}
X src;
};
是好还是坏?