struct two_elements {
int x;
double y;
};
struct five_elements {
std::string one;
std::unique_ptr<int> two;
int * three;
char four;
std::array<two_elements, 10> five;
};
struct anything {
template<class T> operator T()const;
};
namespace details {
template<class T, class Is, class=void>
struct can_construct_with_N:std::false_type {};
template<class T, std::size_t...Is>
struct can_construct_with_N<T, std::index_sequence<Is...>, std::void_t< decltype(T{(void(Is),anything{})...}) >>:
std::true_type
{};
}
template<class T, std::size_t N>
using can_construct_with_N=details::can_construct_with_N<T, std::make_index_sequence<N>>;
namespace details {
template<std::size_t Min, std::size_t Range, template<std::size_t N>class target>
struct maximize:
std::conditional_t<
maximize<Min, Range/2, target>{} == (Min+Range/2)-1,
maximize<Min+Range/2, (Range+1)/2, target>,
maximize<Min, Range/2, target>
>
{};
template<std::size_t Min, template<std::size_t N>class target>
struct maximize<Min, 1, target>:
std::conditional_t<
target<Min>{},
std::integral_constant<std::size_t,Min>,
std::integral_constant<std::size_t,Min-1>
>
{};
template<std::size_t Min, template<std::size_t N>class target>
struct maximize<Min, 0, target>:
std::integral_constant<std::size_t,Min-1>
{};
template<class T>
struct construct_searcher {
template<std::size_t N>
using result = ::can_construct_with_N<T, N>;
};
}
template<class T, std::size_t Cap=20>
using construct_airity = details::maximize< 0, Cap, details::construct_searcher<T>::template result >;
这会对从 0 到 20 的最长构造通风进行二分搜索T
。20 是一个常数,您可以在编译时和内存成本上随意增加它。
活生生的例子。
如果你的结构中的数据不能从它自己类型的右值构造,它不会在 C++14 中工作,但我相信在 C++17 中会发生 guanteed elision (!)
将其转换为结构化绑定需要的不仅仅是一堆手动代码。但是一旦你有了,你应该能够问诸如“这是什么第三种类型struct
”之类的问题。
如果 astruct
可以在不做任何tuple_size
事情的情况下分解为结构化绑定,那么它的空气流通性决定了它需要多少变量。
不幸std::tuple_size
的是,即使在 C++17 中也对 SFINAE 不友好。但是,使用该tuple_size
部分的类型也需要启用 ADL std::get
。
failure_tag get<std::size_t>(Ts const&...)
使用that创建一个命名空间using std::get
。使用它来检测它们是否已经覆盖get<0>
了类型 ( !std::is_same< get_type<T,0>, failure_tag >{}
),如果是,则沿着tuple_element
路径确定通风。将结果元素填充到 a std::tuple
of 中decltype(get<Is>(x))
并返回它。
如果失败,请使用上述construct_airity
方法,并使用它来确定如何在类型上使用结构化绑定。std::tie
为了统一起见,我可能会将其发送到, 中。
我们现在有了tuple_it
它,它接受任何类似结构化绑定的东西并将其转换为引用或值的元组。现在两条路径已经融合,您的通用代码更容易了!