【问题标题】:C++ : a helper to compare variadic unsigned int templates parametersC++:比较可变参数无符号整数模板参数的助手
【发布时间】:2012-08-11 05:21:46
【问题描述】:

在一个混合了 CRTP、可变参数模板、元编程和运算符重载的类中,我想比较两个可变参数 unsigned int 模板参数以进行一些静态断言。我认为辅助结构将是做到这一点的好方法,但我不知道该怎么做。我想到了一些形式:

template<unsigned int... TDIM, unsigned int... TDIM0> struct HelperCheckDimensions
{
    static const bool ok = /* SOMETHING */
};

其中TDIMTDIM0 是我要比较的两个参数。它可以让我输入:

static_assert(HelperCheckDimensions<TDIM..., TDIM0...>::ok, "ERROR : Dimensions are different !");

我希望结果只有在sizeof...(TDIM)==sizeof...(TDIM0) AND TDIM[0] == TDIM0[0], TDIM[1] == TDIM0[1], ..., TDIM[n] == TDIM0[n] 时才为真。

怎么做?

非常感谢。

【问题讨论】:

    标签: c++ c++11 helpers variadic-templates


    【解决方案1】:

    我会说这种形式的类 variadic-template 没有意义:

    template<unsigned int... TDIM, unsigned int... TDIM0> 
    struct HelperCheckDimensions
    {
        //..
    };
    

    这没有意义,因为如果我这样写:

    HelperCheckDimensions<1,2,3,4,5,6> z;
    

    那么TDIMTDIM0 应该是什么?编译器应该如何对参数进行分区?

    这是否正确:

    TDIM = (1,2)
    TDIM0 = (3,4,5,6)
    

    或者这是正确的:

    TDIM = (1)
    TDIM0 = (2,3,4,5,6)
    

    或者这个:

    TDIM = (1,2,3,4)
    TDIM0 = (5,6)
    

    希望这有助于为什么它没有意义。


    来自您的评论:

    非常好的观点!但我的问题仍然悬而未决......也许template&lt;unsigned int... TDIM, typename TFAKE, unsigned int... TDIM0&gt; 形式的东西会起作用?最好的解决方案是什么?

    标准不允许此表单的模板定义:

    template<unsigned int... TDIM, typename TFAKE, unsigned int... TDIM0>
    

    我不知道为什么标准不允许它,即使它对我来说是有意义的,至少在这种情况下(也许它给语言增加了不值得的复杂性)。根据标准,template-parameter-pack 必须是模板定义的 last 参数。

    如果你在 GCC 中编译上面的代码,它会给出这个错误:

    错误:参数包“TDIM”必须在模板参数列表的末尾

    希望对您有所帮助。

    【讨论】:

    • 非常好!但是我的问题仍然悬而未决...也许某些表单模板 会起作用吗?什么是最好的解决方案?
    • 我认为他们不允许这样做的部分原因是这可能导致了他们当时无法想到的错误。从某种意义上说是一种安全,如果他们认为确实没有问题,以后可能会提高。这不会是第一次/
    【解决方案2】:

    假设您的主模板如下所示:

    template <int ...> struct Foo;
    

    您现在可以制作Foo 比较器:

    template <typename, typename> struct FooCmp : std::false_type { };
    
    template <int A, int B, int ...As, int ...Bs>
    struct FooCmp<Foo<A, As...>, Foo<B, Bs...>>
    : std::integral_constant<bool, A == B && FooCmp<Foo<As...>, Foo<Bs...>>::value>
    { };
    
    template <> struct FooCmp<Foo<>, Foo<>> : std::true_type { };
    

    用法:

    typedef Foo<1, 3, 4> F1;
    typedef Foo<9, 5, 1> F2;
    
    template <typename S, typename T>
    std::enable_if<FooCmp<S, T>::value> do_magic(S s, T t) { /* ... */ }
    
    do_magic(F1{}, F2{});
    

    【讨论】:

    • 是否允许:template &lt;int A, int B, int ...As, int ...Bs&gt;? GCC 说,参数包必须在模板参数列表的末尾
    • @Nawaz 这是有效的,因为包出现在部分专业化中
    • @Mr.Anubis:有了包,你能做的唯一明智的事情就是打开包装,把它们当作头加尾。
    【解决方案3】:

    主类模板不能有两个参数包,你需要使用一些包包装器

    template<unsigned int...T> struct intPack;
    template<typename T, typename Y> struct HelperCheckDimensions;
    
    template<unsigned int lhs, unsigned int...T, unsigned int rhs, unsigned int...Y> struct HelperCheckDimensions<intPack<lhs,T...>, intPack<rhs, Y...>>
    {
    static const bool value = lhs==rhs && HelperCheckDimensions<intPack<T...>, intPack<Y...>>::value;
    };
    template<unsigned int lhs, unsigned int rhs> struct HelperCheckDimensions<intPack<lhs>, intPack<rhs>>
    {
    static const bool value = lhs==rhs;
    };
    

    测试:http://liveworkspace.org/code/200e10548f3fc589f39401ca0b22e7c8

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-04
      • 2016-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多