Ori*_*ent 6 c++ type-traits variadic-templates c++17 structured-bindings
是否可以使用结构化绑定语法确定在方括号中指定的变量名称数量,以匹配简单右侧的数据成员数量struct?
我想创建通用库的一部分,它使用结构化绑定将任意类分解为其组成部分.目前没有可变版本的结构化绑定(并且,我认为,不能用于当前提出的语法),但我首先想到的是对一些函数进行一组重载decompose(),它将struct参数分解为一组成分.decompose()应该通过参数的数量(即struct数据成员)来重载.目前constexpr if 语法也可以用来发送它.但是,我如何sizeof...为上述目的模拟类似于运算符的东西?我不能auto [a, b, c]在SFINAE结构中的某处使用语法,因为它是一个分解声明和AFAIK任何声明都不能在里面使用decltype,我也不能在lambda函数体中使用它,因为lambda函数也不能在模板参数中使用.
当然我想拥有内置运算符(语法类似于sizeof[] S/ sizeof[](S)for class S),但是类似下面的东西也是可以接受的:
template< typename type, typename = void >
struct sizeof_struct
{
};
template< typename type >
struct sizeof_struct< type, std::void_t< decltype([] { auto && [p1] = std::declval< type >(); void(p1); }) > >
: std::integral_constant< std::size_t, 1 >
{
};
template< typename type >
struct sizeof_struct< type, std::void_t< decltype([] { auto && [p1, p2] = std::declval< type >(); void(p1); void(p2); }) > >
: std::integral_constant< std::size_t, 2 >
{
};
... etc up to some reasonable arity
Run Code Online (Sandbox Code Playgroud)
也许constexprlambda将允许我们将它们用于模板的参数中.你怎么看?
即将到来的概念会有可能吗?
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 >;
Run Code Online (Sandbox Code Playgroud)
这是一个二进制搜索T从0到20 的最长构造空间.20是一个常量,你可以在编译时和内存成本增加它.
实例.
如果你的struct中的数据不能用它自己类型的rvalue构造,那么它在C++ 14中不起作用,但我相信在这里C++ 17中会发生guanteed elision(!)
将其转换为结构化绑定需要一堆手动代码.但是一旦你有了,你应该能够提出诸如"这是什么的第三类struct"之类的问题.
如果a struct可以在没有tuple_size完成任务的情况下被分解为结构化绑定,那么它的空间性决定了它需要多少变量.
不幸的std::tuple_size是,即使在C++ 17中,SFINAE也不友好.但是,使用该tuple_size部件的类型也需要启用ADL std::get.
创建一个命名空间failure_tag get<std::size_t>(Ts const&...)是using std::get.使用它来检测它们是否已get<0>在类型(!std::is_same< get_type<T,0>, failure_tag >{})上覆盖,如果是,则沿着tuple_element路径确定空气.东西所产生的要素引入std::tuple的decltype(get<Is>(x)),并返回.
如果失败,请使用上面的内容construct_airity,并使用它来弄清楚如何在类型上使用结构化绑定.std::tie为了统一,我可能会把它发送到一个.
我们现在拥有tuple_it任何类似结构化绑定的东西,并将其转换为引用或值的元组.现在两条路径都已融合,您的通用代码更容易!