成员初始化器列表:初始化返回元组的函数中的两个成员

时间:2022-05-06 00:31:12

Can multiple members be initialized in the member initializer list from a tuple obtained by a function?

从一个函数获得的元组的成员初始化器列表中可以初始化多个成员吗?

With returning multiple values via tuples becoming more popular I hope there is a solution for this. I see no reason other than a language limitation why this would not be possible.

随着通过元组返回多个值变得越来越流行,我希望有一个解决方案。我认为除了语言限制之外,没有其他原因可以解释为什么这是不可能的。


This is a mcve for what I have:

这是我所拥有的mcve:

auto new_foo(std::size_t size) -> std::tuple<std::unique_ptr<char[]>, int*>
{
    auto buffer = std::make_unique<char[]>(size * sizeof(int) + 8);
    auto begin = static_cast<int*>(static_cast<void*>(buffer.get() + 4));
    return std::make_tuple(std::move(buffer), begin);
}

struct X {
    std::unique_ptr<char[]> buffer_{nullptr};
    int* begin_{nullptr};
    std::size_t size_{0};

    X(std::size_t size) : size_{size}
    {
        std::tie(buffer_, begin_) = new_foo(size);
    }
};

Can this be done?:

这个可以做吗?

    X(std::size_t size)
        : buffer_{ ??? },
          begin_{ ??? },
          size_{size}
    {
    }

I simply cannot call new_foo once for each member initialization (as it returns another tuple with every call). So

对于每个成员初始化,我不能只调用一次new_foo(因为每次调用都返回另一个元组)。所以

    X(std::size_t size)
        : buffer_{std:get<0>(new_foo(size)},
          begin_{std:get<1>(new_foo(size)},
          size_{size}
    {
    }

it's not possible (even if it this wasn't the case, calling multiple times to get the same result is less than optimal)

这是不可能的(即使不是这样,调用多次来得到相同的结果也不太理想)

Another solution I thought about was to hold the members as a tuple. I discarded that as I need the two members properly named inside the class and not accessed with get<0> and get<1>.

我想到的另一个解决方案是将成员作为一个元组。我丢弃了它,因为我需要在类中正确命名的两个成员,并且不使用get<0>和get<1>进行访问。

Yet another workaround would be to create a simple separate struct to hold the two members. This way they would have names, but add another level of qualifier, and possible I would have to create a copy ctor for it (because of the unique_ptr).

另一个解决方案是创建一个单独的结构体来容纳这两个成员。这样,它们就有了名称,但是添加了另一个级别的限定符,并且可能需要为它创建一个复制ctor(因为有unique_ptr)。


As reported here C++1z will have Structured bindings (D0144R0) which will make this possible:

如本文所述,c++ 1z将具有结构化绑定(D0144R0),这将使这成为可能:

auto {x,y,z} = f();

As I didn't find the full paper, I cannot tell if this will help in the context of member initializer list. I suspect not.

因为我没有找到完整的论文,所以我不能说这在成员初始化器列表的上下文中是否有用。我怀疑不是。

1 个解决方案

#1


14  

Define another (possibly private) constructor that takes the tuple and delegate to it.

定义另一个(可能是私有的)构造函数,该构造函数接受元组并将其委托给它。

  private:
    X(std::tuple<std::unique_ptr<char>, int*> t, std::size_t size)
            : buffer_{std::move(std:get<0>(t))},
              begin_{std:get<1>(t)},
              size_{size}
    { }

 public:
    X(std::size_t size) : X{new_foo(size), size}
    { }

#1


14  

Define another (possibly private) constructor that takes the tuple and delegate to it.

定义另一个(可能是私有的)构造函数,该构造函数接受元组并将其委托给它。

  private:
    X(std::tuple<std::unique_ptr<char>, int*> t, std::size_t size)
            : buffer_{std::move(std:get<0>(t))},
              begin_{std:get<1>(t)},
              size_{size}
    { }

 public:
    X(std::size_t size) : X{new_foo(size), size}
    { }