如何将 std::tuple 元素移出类对象?

问题描述 投票:0回答:1

问题:

我想将元素移出类成员元组类型变量,但我想知道是否允许使用以下代码(接近最小示例,仅限于 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

问题:

  1. 如果是通过像

    m_tuple
    这样的
    &&
    限定方法完成的,是否允许从像
    moveB<>()
    这样的成员移动?

  2. 是否允许多次“调用”

    std::move(*this)
    ,就像在
    moveBs<>()
    中的参数包扩展中完成的那样?

c++ c++14 undefined-behavior move-semantics stdtuple
1个回答
0
投票

如果是通过像

m_tuple
这样的
&&
限定方法完成的,是否允许从像
moveB<>()
这样的成员移动?

是的

是否允许多次“调用”

std::move(*this)
,就像在
moveBs<>()
中的参数包扩展中完成的那样?

是的。

您不想做的就是从可能最终处于有效但不确定状态的资源中多次移动。你的代码没有做到这一点。

© www.soinside.com 2019 - 2024. All rights reserved.