gpt4 book ai didi

c++ - 返回 C++17 可变参数模板的可变参数聚合(结构)和语法 'construction deduction guide'

转载 作者:可可西里 更新时间:2023-11-01 18:29:11 26 4
gpt4 key购买 nike

使用模板结构,例如下面的 many,可以返回一组固定的可能不可移动的对象,并使用 c++17 结构化绑定(bind)(auto [a, b, c] = f(); 声明变量 abc 并从 分配它们的值f 返回例如结构或元组)。

template<typename T1,typename T2,typename T3>
struct many {
T1 a;
T2 b;
T3 c;
};

// guide:
template<class T1, class T2, class T3>
many(T1, T2, T3) -> many<T1, T2, T3>;

auto f(){ return many{string(),5.7, unmovable()}; };

int main(){
auto [x,y,z] = f();
}

如这两个问题和答案中所述(Do std::tuple and std::pair support aggregate initialization?尤其是 accepted answer by ecatmur , 还有 Multiple return values (structured bindings) with unmovable types and guaranteed RVO in C++17 ), std::tuple 不支持聚合初始化。这意味着它不能用于保存和返回不可移动的类型。但是像 many 这样的简单结构可以做到这一点,这就引出了一个问题:

是否可以创建适用于任意数量参数的 many 的可变版本?

更新:在 many 的模板化版本中,是否允许使用以下指南语法?

template<typename Args...>    
many(Args...) -> many<Args...>;

最佳答案

在 C++17 中聚合初始化将能够初始化公共(public)基类。所以你可以使用继承+包扩展来构建这样的类。要使其与结构化绑定(bind)一起使用,您必须公开元组接口(interface):specialize std::tuple_sizestd::tuple_element并提供get您类(class)的功能:

//Headers used by "many" class implementation
#include <utility>
#include <tuple>

namespace rw {
namespace detail {

template <size_t index, typename T>
struct many_holder
{ T value; };

template <typename idx_seq, typename... Types>
struct many_impl;

template <size_t... Indices, typename... Types>
struct many_impl<std::index_sequence<Indices...>, Types...>: many_holder<Indices, Types>...
{};

}

template <typename... Types>
struct many: detail::many_impl<typename std::make_index_sequence<sizeof...(Types)>, Types...>
{};

template<size_t N, typename... Types>
auto get(const rw::many<Types...>& data) -> const std::tuple_element_t<N, rw::many<Types...>>&
{
const rw::detail::many_holder<N, std::tuple_element_t<N, rw::many<Types...>>>& holder = data;
return holder.value;
}

}

namespace std {
template <typename... Types>
struct tuple_size<rw::many<Types...>> : std::integral_constant<std::size_t, sizeof...(Types)>
{};

template< std::size_t N, class... Types >
struct tuple_element<N, rw::many<Types...> >
{ using type = typename tuple_element<N, std::tuple<Types...>>::type; };
}

//Headers used for testing
#include <iostream>
#include <string>

int main()
{
rw::many<int, std::string, int> x = {42, "Hello", 11};
std::cout << std::tuple_size<decltype(x)>() << '\n' << rw::get<1>(x);
}

演示(目前仅适用于 clang 3.9): http://melpon.org/wandbox/permlink/9NBqkcbOuURFvypt

注意事项:

  • 在演示中有一个注释掉的 nth_type 实现, 你可以用来补充 tuple_element直接而不是将其推迟到tuple_element<tuple>实现。
  • get<many>应该是 many 的成员函数或放置在关联的命名空间中以使结构化绑定(bind)起作用。你不应该重载 std::get (无论如何都是 UB)。
  • 我离开了 get 的实现对于非常量引用和 r 值引用作为读者的练习。
  • 没有使用结构化绑定(bind)和指南的示例,因为 clang 不支持它们(事实上我不知道有哪个编译器支持它们)。理论上
    template<typename... Types> many(Types...) -> many<Types...>;应该可以。

关于c++ - 返回 C++17 可变参数模板的可变参数聚合(结构)和语法 'construction deduction guide',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38393302/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com