验证(使用static_assert)元组类型遵循某种顺序(有状态编译时检查)

问题描述 投票:1回答:1

对于相对较旧的软件中的某些序列化应用程序,我的类型看起来像这样:

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;

这些常数为static constexpr,代表某些数据库表,向量为某种存储类型(细节不重要)。

为了确保这种“类型”类型的安全,并确保将来一切正常,我需要确保在元组中添加其他类型的用户使用序列号。所以另一个元素应该是这个

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;

[我的解决方案到目前为止失败了,我很感谢有人对此提供意见:

template <typename Tuple>
struct tuple_assert;

template <typename... Ts>
struct tuple_assert<boost::tuple<Ts...>> {
  static constexpr void verify() {
    __verify<std::integral_constant<uint32_t, 0>, Ts...>();
  }

  static constexpr void __verify() {}

  template <typename Count, typename Pair>
  static constexpr void __verify() {
        static_assert(std::is_same<typename Pair::first_type, Count>::value, "");
  }

  template <typename Count, typename Pair, typename... Ts2>
  static constexpr void __verify() {
    static_assert(std::is_same<typename Pair::first_type, Count>::value, "");

    __verify<std::integral_constant<uint32_t, Pair::first_type::value + 1>,
             Ts...>();
  }
};

所以您看到的是我创建了一个状态(Count),并且每次迭代都在增加计数。但这以某种方式达到了错误的状态,当我在此调用中使用它时会触发static_assert:

tuple_assert<T>::verify(); // `T` is the type I mentioned at the very beginning

See my solution that doesn't work online.

我在做什么错?

c++ templates tuples c++14 sfinae
1个回答
1
投票

您的代码有些错误。第一个是在此行中,模板参数列表扩展中的错字:

__verify<std::integral_constant<uint32_t, Pair::first_type::value + 1>,
         Ts...>();

应该是:

__verify<std::integral_constant<uint32_t, Pair::first_type::value + 1>,
         Ts2...>(); 

但是可惜它无法解决。 boost::tuple里面有一些nulltype_t奇怪的typedef。将其更改为std::tuple仍无法解决,因为您的__verify函数调用不明确。

这是我所做的肯定有效的方法:

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 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<std::tuple<Args...>> : verify_types<0, Args...>{};

Live example

© www.soinside.com 2019 - 2024. All rights reserved.