我想创建一个包含硬编码元素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{
是什么原因?它只是模板中的语法错误吗?或者这个想法是不可能的?如果不可能,还有其他方法可以检查数组是否在编译时排序吗?
答案 0 :(得分:4)
您需要部分模板专业化。
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, "");
}
答案 1 :(得分: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;
}
答案 2 :(得分:1)
您正在尝试使用partial template specialization。这允许为类模板创建多个定义。
但即使使用此功能,您只需创建一个类型的声明。宣言是这样的:
template<int... I>
struct s;
您甚至可以将其与定义结合使用:
template<int... I>
struct s {};
在s
的声明后面,您可以添加其他定义。但是不允许添加与第一个不同的声明。要添加定义(并且没有声明),您必须将模板参数添加到类型的名称。请注意以下定义中名称后面的<10>
。该定义仅用于类型s<10>
:
template<>
struct s<10> {};
您还可以使用更通用的定义。以下定义仅用于s<x>
,其中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();};
};
答案 3 :(得分:1)
您不需要精心设计的解决方案。 首先你需要定义正确的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}));
}