【问题标题】:how to check if hardcode int array is sorted at compile time using template recursion?如何使用模板递归检查硬编码 int 数组是否在编译时排序?
【发布时间】:2016-04-24 08:39:13
【问题描述】:

我想创建一个包含硬编码元素L(例如:1,2,3,3)的数组的程序,并使用模板变量参数来检查元素是否已排序,如果未排序,它将失败在 static_assert 处编译,但现在程序根本无法编译:

#include <stdio.h>
#include <vector>
template<int first,int second,int... args>
struct s{
    enum{e=first<=second && s<second,args...>::e};
};

template<int first,int second>
struct s{
    enum{e=first<=second};
};
#define L 1,2,3,3
//static_assert(s<L>::e!=0,"");
int a[]={L};
int main(){
    printf("%d\n",s<L>::e);
    return 0;
}

编译错误说:

abc.cpp:5:29: error: too few template arguments for class template 's'
    enum{e=first<=second && s<second,args...>::e};
                        ^
abc.cpp:5:29: note: in instantiation of template class 's<3, 3>' requested here
    enum{e=first<=second && s<second,args...>::e};
                        ^
abc.cpp:5:29: note: in instantiation of template class 's<2, 3, 3>' requested here
    enum{e=first<=second && s<second,args...>::e};
                        ^
abc.cpp:16:19: note: in instantiation of template class 's<1, 2, 3, 3>' requested here
    printf("%d\n",s<L>::e);
              ^
abc.cpp:4:8: note: template is declared here
    struct s{

是什么原因?它只是模板中的语法错误吗?或者这个想法是不可能的?如果不可能,有没有其他方法可以在编译时检查数组是否排序?

【问题讨论】:

  • Consexpr 函数应该简单得多。
  • g++和clang++都给我一个关于模板“重新声明”的错误,这是一个重要的错误。

标签: c++ arrays sorting templates compile-time


【解决方案1】:

您需要部分模板特化。

template<int... Args>
struct IsSorted {
    static constexpr bool value = true;
};

template<int A, int B, int... Args>
struct IsSorted<A, B, Args...> {
    static constexpr bool value = A <= B && IsSorted<B, Args...>::value;
};

int main() {
    static_assert(IsSorted<>::value, "");
    static_assert(IsSorted<1>::value, "");
    static_assert(IsSorted<1, 2>::value, "");
    static_assert(!IsSorted<2, 1>::value, "");
    static_assert(IsSorted<1, 2, 3>::value, "");
    static_assert(!IsSorted<1, 3, 2>::value, "");
}

【讨论】:

    【解决方案2】:

    部分模板特化的语法错误

    #include <stdio.h>
    #include <vector>
    template<int first,int second,int... args>
    struct s{
        enum{e=first<=second && s<second,args...>::e};
    };
    
    template<int first,int second>
    struct s<first, second>{ // <----- <first, second> here
        enum{e=first<=second};
    };
    
    #define L 1,2,3,3
    #define L2 1,2,4,3
    //static_assert(s<L>::e!=0,"");
    int a[]={L};
    int main(){
        printf("%d\n",s<L>::e);
        printf("%d\n",s<L2>::e);
        return 0;
    }
    

    Online Demo at Coilru

    【讨论】:

      【解决方案3】:

      您正在尝试使用partial template specialization。这允许为一个类模板进行多个定义。

      但即使使用此功能,您也只需创建一个类型声明。声明是这样的:

      template<int... I>
      struct s;
      

      您甚至可以将其与定义结合起来:

      template<int... I>
      struct s {};
      

      s 的声明之后,您可以添加其他定义。但不允许添加与第一个不同的声明。要添加定义(而不是声明),您必须将模板参数添加到类型的名称中。请注意以下定义中名称后面的&lt;10&gt;。该定义仅用于s&lt;10&gt;类型:

      template<>
      struct s<10> {};
      

      您还可以使用更通用的定义。以下定义仅用于s&lt;x&gt;,其中 x 是某个整数。它不会用于具有多个模板参数的类型。

      template<int I>
      struct s<I> {}
      

      我会以这种方式使用 C++11 实现您的 s

      template<int... args>
      struct s {
          static constexpr bool value() {return true;}
      };
      
      template<int first, int second, int... args>
      struct s<first, second, args...> {
          static constexpr bool value() {return first <= second && s<second,args...>::value();};
      };
      

      【讨论】:

        【解决方案4】:

        您不需要为此制定详细的解决方案。 首先你需要定义正确的 is_sorted 因为在 C++20 之前 is_sorted 不是 constexpr 然后使用它。

        #define L1 1,2,3,3
        #define L2 1,2,1,3
        
        template<typename T>
        constexpr bool c_is_sorted(const std::initializer_list<T>& il){
            for(auto it= il.begin(); it!=il.end()-1;it++){
                if (*(it+1)<*it) {
                    return false;
                }
            }
            return true;
        }
        
        int main(){
            static_assert(c_is_sorted({L1}));
            static_assert(!c_is_sorted({L2}));
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-03-11
          • 2015-08-24
          • 1970-01-01
          • 2022-06-10
          • 2019-01-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多