我想将元素移出类成员元组类型变量,但我想知道是否允许使用以下代码(接近最小示例,仅限于 C++14):
#include <tuple>
#include <iostream>
// For testing, assume a move-only class template:
enum class Index { idx1, idx2, idx3 };
template <Index I>
struct B {
~B() = default;
B(B&&) = default;
B& operator= (B&&) = default;
B(B const&) = delete;
B& operator= (B const&) = delete;
Index getIndex() { return I; }
};
// Class to consider
template <Index... Is_>
class A
{
public:
A(B<Is_>&&... _b) : m_tuple{std::move(_b)...} {}
template <Index... Js_>
std::tuple<B<Js_>...> moveBs() &&
{
return { std::move(*this).template moveB<Js_>()... };
}
private:
template <Index J_>
B<J_> moveB() &&
{
return std::get<B<J_>>(std::move(m_tuple));
}
std::tuple<B<Is_>...> m_tuple;
};
// Output only as an example, to try out
void print(Index _i)
{
std::cout << ( (_i == Index::idx1) ? "Index::idx1"
: (_i == Index::idx2) ? "Index::idx2"
: (_i == Index::idx3) ? "Index::idx3"
: "unknown!")
<< std::endl;
}
int main()
{
A<Index::idx1,
Index::idx2,
Index::idx3> a{ B<Index::idx1>{},
B<Index::idx2>{},
B<Index::idx3>{} };
B<Index::idx1> b1{};
B<Index::idx2> b2{};
// Call to consider
std::tie(b1, b2) = std::move(a).moveBs<Index::idx1,
Index::idx2>();
// Usage of objects b1,b2 - verify the result of the previous call
print(b1.getIndex());
print(b2.getIndex());
}
Clang 和 GCC 编译器接受它,但从对象
a
移动几次,因为它是通过 moveBs<Js_>()
完成的,感觉是非法的。
选择的选项:
--std=c++14 -O3 -Wall -Wextra -Wshadow -Wconversion -Wpedantic -Werror
。
如果是通过像
m_tuple
这样的&&
限定方法完成的,是否允许从像moveB<>()
这样的成员移动?
是否允许多次“调用”
std::move(*this)
,就像在moveBs<>()
中的参数包扩展中完成的那样?
如果是通过像
这样的m_tuple
限定方法完成的,是否允许从像&&
这样的成员移动?moveB<>()
是的
是否允许多次“调用”
,就像在std::move(*this)
中的参数包扩展中完成的那样?moveBs<>()
是的。
您不想做的就是从可能最终处于有效但不确定状态的资源中多次移动。你的代码没有做到这一点。