C++ 验证(使用static_assert)元组类型是否遵循某种顺序(有状态编译时检查)
对于相对较旧的软件中的某些序列化应用程序,我有如下类型:C++ 验证(使用static_assert)元组类型是否遵循某种顺序(有状态编译时检查),c++,templates,tuples,c++14,variadic-templates,C++,Templates,Tuples,C++14,Variadic Templates,对于相对较旧的软件中的某些序列化应用程序,我有如下类型: using T = boost::tuple< std::pair<std::integral_constant<uint32_t, 0>, std::vector<int>>, std::pair<std::integral_constant<uint32_t, 1>, std::vector<double>> >; T even
using T = boost::tuple<
std::pair<std::integral_constant<uint32_t, 0>, std::vector<int>>,
std::pair<std::integral_constant<uint32_t, 1>, std::vector<double>>
>;
T events;
这是错误的,不应编译:
using T = boost::tuple<
std::pair<std::integral_constant<uint32_t, 0>, std::vector<int>>,
std::pair<std::integral_constant<uint32_t, 1>, std::vector<double>>,
std::pair<std::integral_constant<uint32_t, 2>, std::vector<float>>
>;
T events;
using T = boost::tuple<
std::pair<std::integral_constant<uint32_t, 0>, std::vector<int>>,
std::pair<std::integral_constant<uint32_t, 1>, std::vector<double>>,
std::pair<std::integral_constant<uint32_t, 1>, std::vector<float>>
>;
T events;
我做错了什么?您的代码有几处错误。第一个是在这一行,模板参数列表扩展中的一个输入错误:
__verify<std::integral_constant<uint32_t, Pair::first_type::value + 1>,
Ts...>();
boost::tuple
这个有点复杂
template<unsigned V, class T, class ...Args>
struct verify_types {
static constexpr bool value = V == T::first_type::value && verify_types<V+1, Args...>::value;
};
template<unsigned V, class ...Args>
struct verify_types<V, boost::tuples::null_type, Args...> {
static constexpr bool value = true;
};
template<unsigned V, class T>
struct verify_types<V, T> {
static constexpr bool value = V == T::first_type::value;
};
template<class T>
struct verify_tuple : std::false_type {};
template<class ...Args>
struct verify_tuple<boost::tuple<Args...>> : verify_types<0, Args...>{};
模板
结构验证类型{
静态constexpr bool value=V==T::first\u type::value&&verify\u types::value;
};
模板
结构验证类型{
静态constexpr布尔值=真;
};
模板
结构验证类型{
静态constexpr bool value=V==T::first\u type::value;
};
模板
struct verify_tuple:std::false_type{};
模板
struct verify_tuple是否太晚而无法播放
对不起,但是。。。为什么不直接使用模板演绎法呢
像
template <typename>
struct check_tuple;
template <template <typename...> class Tpl, std::uint32_t ... Is,
typename ... Ts>
struct check_tuple<Tpl<
std::pair<std::integral_constant<std::uint32_t, Is>, Ts>...>>
: public std::is_same<
std::integer_sequence<std::uint32_t, Is...>,
std::make_integer_sequence<std::uint32_t, sizeof...(Is)>>
{ };
--编辑--
我错了:boost::tuple
未定义为std::tuple
,接收模板类型的可变列表,但具有类型模板参数的固定数字(10,但应该可以修改),默认为boost::tuples::null\u type
所以,举个例子
using T1 = boost::tuple<
std::pair<std::integral_constant<std::uint32_t, 0>, std::vector<int>>,
std::pair<std::integral_constant<std::uint32_t, 1>, std::vector<double>>,
std::pair<std::integral_constant<std::uint32_t, 2>, std::vector<float>>
>;
这打破了我先前的解决方案,因为
template <template <typename...> class Tpl, std::uint32_t ... Is,
typename ... Ts>
struct check_tuple<Tpl<
std::pair<std::integral_constant<std::uint32_t, Is>, Ts>...>>
现在,check\u tuple
可以重写如下
template <typename T,
typename = decltype(convert_tuple(std::declval<T>()))>
struct check_tuple;
template <typename BT, std::uint32_t ... Is, typename ... Ts>
struct check_tuple<BT, std::tuple<
std::pair<std::integral_constant<std::uint32_t, Is>, Ts>...>>
: public std::is_same<
std::integer_sequence<std::uint32_t, Is...>,
std::make_integer_sequence<std::uint32_t, sizeof...(Is)>>
{ };
这些数字是否应该按顺序排列,或者只要它们是唯一的,是否允许按任何顺序排列?你能跳过一个数字吗?从修复最后一个\uu verify
中的一个输入错误开始,在这里你可能想扩展Ts2…
,而不是Ts…。
@Albjenow它们应该按顺序排列,并且应该从0开始。从0开始并不重要,因为没有人会改变它。@PiotrSkotnicki这不是打字错误。它会掩盖类模板类型。@量子物理学家你误解了我说的话谢谢,但我需要这个用于boost::tuple
,而不是std::tuple
。。。它的工作原理不同,因为boost
缺少一些函数。@量子物理学家为boost::tuple
进行了更新。但是它在实现上很麻烦而且过时,所以我建议切换到std
我可以建议您列出std::tuple
和boost::tuple
的两种解决方案吗?两者都很有价值!很不错的!你得到我的支持;-)。我想知道这是否适用于boost::tuple
?我以后可能会试试。@QuantumPhysician-我没有安装boost的平台,但是。。。为什么不呢?我使用了模板类Tpl
来截取每个模板类型,这些模板类型作为模板参数接收可变类型列表。它实际上不适用于boost::tuple
。我在想原因。我不熟悉您使用的一些模板,所以我不确定这需要多长时间。如果你能尝试一下(即使是在今天晚些时候),那就太好了。@QuantumPhysica学家-我很惊讶:据我所知,boost::tuple
被精确地定义为std::tuple
:接收一个类型的可变列表。。。我将尝试在安装了boosts的平台上进行验证。@QuantumPhysicast-不,我错了:boost::tuple
不同于std::tuple
:不接收可变参数列表,但只接收10个模板参数,默认为boost::tuples::null\u type
;因此,T1
有三个std::pair
,后面是七个boost::tuples::null\u type
。这是个问题。。。但我有一个半想法。。。请给我一些时间详细说明。
template <typename>
struct check_tuple;
template <template <typename...> class Tpl, std::uint32_t ... Is,
typename ... Ts>
struct check_tuple<Tpl<
std::pair<std::integral_constant<std::uint32_t, Is>, Ts>...>>
: public std::is_same<
std::integer_sequence<std::uint32_t, Is...>,
std::make_integer_sequence<std::uint32_t, sizeof...(Is)>>
{ };
#include <tuple>
#include <vector>
using T1 = std::tuple<
std::pair<std::integral_constant<std::uint32_t, 0>, std::vector<int>>,
std::pair<std::integral_constant<std::uint32_t, 1>, std::vector<double>>,
std::pair<std::integral_constant<std::uint32_t, 2>, std::vector<float>>
>;
using T2 = std::tuple<
std::pair<std::integral_constant<std::uint32_t, 0>, std::vector<int>>,
std::pair<std::integral_constant<std::uint32_t, 1>, std::vector<double>>,
std::pair<std::integral_constant<std::uint32_t, 1>, std::vector<float>>
>;
template <typename>
struct check_tuple;
template <template <typename...> class Tpl, std::uint32_t ... Is,
typename ... Ts>
struct check_tuple<Tpl<
std::pair<std::integral_constant<std::uint32_t, Is>, Ts>...>>
: public std::is_same<
std::integer_sequence<std::uint32_t, Is...>,
std::make_integer_sequence<std::uint32_t, sizeof...(Is)>>
{ };
int main()
{
static_assert( check_tuple<T1>::value == true, "!" );
static_assert( check_tuple<T2>::value == false, "!" );
}
using T1 = boost::tuple<
std::pair<std::integral_constant<std::uint32_t, 0>, std::vector<int>>,
std::pair<std::integral_constant<std::uint32_t, 1>, std::vector<double>>,
std::pair<std::integral_constant<std::uint32_t, 2>, std::vector<float>>
>;
using T1 = boost::tuple<
std::pair<std::integral_constant<std::uint32_t, 0>, std::vector<int>>,
std::pair<std::integral_constant<std::uint32_t, 1>, std::vector<double>>,
std::pair<std::integral_constant<std::uint32_t, 2>, std::vector<float>>,
boost::tuples::null_type,
boost::tuples::null_type,
boost::tuples::null_type,
boost::tuples::null_type,
boost::tuples::null_type,
boost::tuples::null_type,
boost::tuples::null_type
>;
template <template <typename...> class Tpl, std::uint32_t ... Is,
typename ... Ts>
struct check_tuple<Tpl<
std::pair<std::integral_constant<std::uint32_t, Is>, Ts>...>>
template <typename T>
struct get_tuple
{ using type = std::tuple<T>; } ;
template <>
struct get_tuple<boost::tuples::null_type>
{ using type = std::tuple<>; };
template <typename ... Ts>
auto convert_tuple (boost::tuple<Ts...>)
-> decltype( std::tuple_cat(std::declval<typename get_tuple<Ts>::type>()...) );
template <typename T,
typename = decltype(convert_tuple(std::declval<T>()))>
struct check_tuple;
template <typename BT, std::uint32_t ... Is, typename ... Ts>
struct check_tuple<BT, std::tuple<
std::pair<std::integral_constant<std::uint32_t, Is>, Ts>...>>
: public std::is_same<
std::integer_sequence<std::uint32_t, Is...>,
std::make_integer_sequence<std::uint32_t, sizeof...(Is)>>
{ };
#include <tuple>
#include <vector>
#include "boost/tuple/tuple.hpp"
using T1 = boost::tuple<
std::pair<std::integral_constant<std::uint32_t, 0>, std::vector<int>>,
std::pair<std::integral_constant<std::uint32_t, 1>, std::vector<double>>,
std::pair<std::integral_constant<std::uint32_t, 2>, std::vector<float>>
>;
using T2 = boost::tuple<
std::pair<std::integral_constant<std::uint32_t, 0>, std::vector<int>>,
std::pair<std::integral_constant<std::uint32_t, 1>, std::vector<double>>,
std::pair<std::integral_constant<std::uint32_t, 1>, std::vector<float>>
>;
template <typename T>
struct get_tuple
{ using type = std::tuple<T>; } ;
template <>
struct get_tuple<boost::tuples::null_type>
{ using type = std::tuple<>; };
template <typename ... Ts>
auto convert_tuple (boost::tuple<Ts...>)
-> decltype( std::tuple_cat(std::declval<typename get_tuple<Ts>::type>()...) );
template <typename T,
typename = decltype(convert_tuple(std::declval<T>()))>
struct check_tuple;
template <typename BT, std::uint32_t ... Is, typename ... Ts>
struct check_tuple<BT, std::tuple<
std::pair<std::integral_constant<std::uint32_t, Is>, Ts>...>>
: public std::is_same<
std::integer_sequence<std::uint32_t, Is...>,
std::make_integer_sequence<std::uint32_t, sizeof...(Is)>>
{ };
int main()
{
static_assert( check_tuple<T1>::value == true, "!" );
static_assert( check_tuple<T2>::value == false, "!" );
}