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

时间:2016-02-11 23:19:00

标签: c++ tuples c++14 c++17 initialization-list

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

通过元组返回多个值变得越来越流行,我希望有一个解决方案。除了语言限制之外,我认为没有其他理由可以解决这个问题。

这是我所拥有的一切:

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);
    }
};

可以这样做吗?:

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

我无法为每个成员初始化调用new_foo一次(因为它会在每次调用时返回另一个元组)。所以

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

它是不可能的(即使这不是这种情况,多次调用以获得相同的结果也不是最佳的)

我想到的另一个解决方案是将成员作为一个元组。我放弃了,因为我需要在类中正确命名的两个成员,而不是get<0>get<1>访问。

另一种解决方法是创建一个简单的单独结构来保存这两个成员。这样他们就会有名字,但是添加另一级限定符,并且我可能需要为它创建一个副本ctor(因为unique_ptr)。

报告here C++1z将有结构化绑定(D0144R0),这将使这成为可能:

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

由于我没有找到完整的论文,我无法确定这是否有助于成员初始化列表的上下文。我怀疑不是。

1 个答案:

答案 0 :(得分:14)

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

  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}
    { }