Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 验证(使用static_assert)元组类型是否遵循某种顺序(有状态编译时检查)_C++_Templates_Tuples_C++14_Variadic Templates - Fatal编程技术网

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, "!" );
 }