【问题标题】:How to check values in mpl::vector_c?如何检查 mpl::vector_c 中的值?
【发布时间】:2020-03-01 11:42:34
【问题描述】:

the tutorial是exersize,需要的地方:

如果 N 包含 0 或 1 以外的数字,则向二进制模板添加错误检查会导致编译错误

使用标准功能就足够简单了:

template <int N>
struct Binary {
  static_assert(N == 0 || N == 1, "binary have to be 0 or 1");
  const int n = N;
};

但是 mpl::vector_c 怎么做呢?例如:

using values = mpl::vector_c<int, 0, 1>;

template<int N,
         typename = typename std::enable_if</*TODO compare N with values from mpl::vector_c*/>::type>
struct Binary {
  const int n = N;
};

【问题讨论】:

    标签: c++ boost metaprogramming


    【解决方案1】:

    部分模板专业化可能会对您有所帮助:

    诀窍是首先以您使用它的方式定义模板(使用 int (N) 和类型(将是 mpl::vector_c),然后将其“分解”成您想要的组件获取访问权限(在这种情况下,vector_c 包含两个整数)。在下面您可以找到适用于具有两个参数的 vector_c 的示例。您还可以将其扩展为使用任意数量的参数(这可能是一个有趣的第二个练习 :) 并且可以使用参数包来实现)。

    #include <boost/mpl/vector_c.hpp>
    
    using namespace boost;
    using values = mpl::vector_c<int, 1, 1>;
    
    template <int N, typename T> struct Binary;
    template <int N, typename t, long a, long b> struct Binary<N, boost::mpl::vector_c<t, a, b>> {
      static_assert(N == a && b == N, "invalid vector_c");
    };
    
    int main() {
      //Binary<1, boost::mpl::vector_c<int, 1, 2>> koo; // commented out as assertion fails
      Binary<1, values> kooo;
    }
    

    您可能会感兴趣的相关链接:

    请注意,此解决方案不适用于标准

    【讨论】:

      【解决方案2】:

      建立在the other answer之上, 您可以在下面找到使用 SFINAE 的解决方案,如问题中所示,使用 enable_if

      这比我最初预期的要复杂一些,因为不知何故,在部分模板特化中为 boost::mpl_vector_c 提供的参数数量与 mpl::vector 的大小不匹配。

      因此,我在下面定义了一个辅助结构,它允许对提供的布尔值可变参数模板的子集执行布尔“与”操作。

      如果 c++17 可用,注释 c++14/c++17 标记的行可以被删除。 如果 c++14 不可用,例如可以通过使用结构中的递归 #value 声明和 _v/_t 后缀分别替换为 [...]::value/type 来替换 index_sequence。

      
      #include <boost/mpl/vector_c.hpp>
      
      #include <tuple>
      
      /// Helper struct which enables to evaluate a conjunction of a subset of a set of booleans.
      template <typename IndexSequence, bool... v> struct PartialConjunction;
      /// Parital template specialization
      template <std::size_t... idx, bool... b>
      struct PartialConjunction<std::index_sequence<idx...>, b...>
          : std::integral_constant<
                bool, (std::get<idx>(std::forward_as_tuple(b...)) && ...)> {};
      /// 'Alias' for the value 
      template <std::size_t S, bool... v> constexpr auto PartialConjunction_v =
          PartialConjunction<decltype(std::make_index_sequence<S>()), v...>::value;
      
      
      /// Actual struct which holds the type of the vector in ::type if it meets the criterion
      template <typename VecType, VecType N, typename MplVector> struct Same; //< c++14
      //template <auto N, typename MplVector> struct Same;                    //< c++17
      template <typename VecType, VecType N, long... a> struct Same<VecType, N, boost::mpl::vector_c<VecType, a...>> {// c++14
      //template <typename VecType, VecType N, long... a> struct Same<N, boost::mpl::vector_c<VecType, a...>> {       // c++17
        using type = boost::mpl::vector_c<VecType, a...>;
        static constexpr auto Size = typename type::size();
        static constexpr auto value = PartialConjunction_v<Size, N == static_cast<VecType>(a)...>;
      };
      /// Alias for the type which performs SFINAE.
      template <typename T, T N, typename VectorType, typename = std::enable_if_t<Same<T, N, VectorType>::value>>  // c++14..
      using Same_t = typename Same<T, N, VectorType>::type;
      //template <auto N, typename VectorType, typename = std::enable_if_t<Same<N, VectorType>::value>>            // c++17..
      //using Same_t = typename Same<N, VectorType>::type;
      
      
      
      int main() {
      
        // For the c++17 version, the first 'int' in the parameter list can be omitted
      
        //Same_t<int, 1, boost::mpl::vector_c<int, 1, 1, 2>> fails;
      
        Same_t<int, 1, boost::mpl::vector_c<int, 1, 1, 1>> ok;
        Same_t<int, 1, boost::mpl::vector_c<int, 1, 1>> okok;
        Same_t<int, 1, boost::mpl::vector_c<int, 1>> okokok;
      }
      
      

      代码示例可以在 CompilerExplorer 中找到here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-22
        • 2013-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多