C++ 我怎样才能强制使用c++;类方法以仅接受少数整数文本?
我正在重构一个类,它当前有一个方法:C++ 我怎样才能强制使用c++;类方法以仅接受少数整数文本?,c++,templates,standards,C++,Templates,Standards,我正在重构一个类,它当前有一个方法: void resize(size_t sz) 在当前代码库中,sz始终为0、1、2或3。 基础类正在从动态分配更改为maxsize==3的预分配数组 如果有人试图将大小调整到sz>3,如何获得生成时错误? 添加运行时检查非常简单。但我宁愿得到一个编译时检查,它会更快地失败 我不想更改任何使用界内整数文本进行调用的现有代码,例如: x.resize(2) 仍应按原样编译 但是如果有人走过来试图 x.resize(4) or x.resize(n) 它
void resize(size_t sz)
在当前代码库中,sz始终为0、1、2或3。
基础类正在从动态分配更改为maxsize==3的预分配数组
如果有人试图将大小调整到sz>3,如何获得生成时错误?
添加运行时检查非常简单。但我宁愿得到一个编译时检查,它会更快地失败
我不想更改任何使用界内整数文本进行调用的现有代码,例如:
x.resize(2)
仍应按原样编译
但是如果有人走过来试图
x.resize(4)
or
x.resize(n)
它应该无法编译或链接
我在考虑一个在int上专门化的模板,它除了{0,1,2,3}之外没有任何定义。但我不确定如何使它在标准C++的范围内做我想要的。
编辑:
我应该详细说明我对使用模板的想法。我很愿意更改resize函数的声明。我不愿意更改呼叫代码
e、 我在想
void resize( ConstructedFromLiteral<0,3> sz)
void resize(ConstructedFromLiteral sz)
或
void resize(ConstructedFromLiteral sz)
void resize(从文本sz构造)
void resize(从文本sz构造)
void resize(从文本sz构造)
无法获得运行时值的编译时检查。想象一下,如果你说
resize(read_some_number_from_disk());
编译器应该如何检查这一点
但是,您可以将函数设置为模板,因为模板参数在编译时已知:
class Foo
{
template <unsigned int N> void resize()
{
static_assert(N < 4, "Error!");
//...
}
//...
};
struct foo {
template <int N>
void resize() {
static_assert(N >= 0 && N < 4);
}
};
class-Foo
{
模板void resize()
{
静态断言(N<4,“错误!”);
//...
}
//...
};
如果没有静态断言,您可以装配自己的静态断言类,该类将无法编译:
template <bool> struct ecstatic_assert; // no definition!
template <> struct ecstatic_assert<true> { } ;
模板结构摇头丸断言;//没有定义!
模板结构{u断言{};
用法:
... resize ... { ecstatic_assert<N < 4> ignore_me; /* ... */ }
。。。调整大小。。。{欣喜若狂的我;/*…*/}
您可以为int{0,1,2,3}创建四个公共内联专用模板。这些将是简单的单行函数,可以调用任何int的私有普通、泛型函数
编辑:对于那些说不能使用专门模板进行编辑的反对者(为什么会投反对票?)
类演示{
私人:
模板
void PrivateFunction(){
cout我会在编译时使用static\u assert
来检查这一点:
class Foo
{
template <unsigned int N> void resize()
{
static_assert(N < 4, "Error!");
//...
}
//...
};
struct foo {
template <int N>
void resize() {
static_assert(N >= 0 && N < 4);
}
};
structfoo{
模板
void resize(){
静态断言(N>=0&&N<4);
}
};
C++11中内置了static\u assert
,但它也是。与专业化相比,它可以避免一些相当繁琐的代码复制。你不能这样做。你不能保持函数调用按原样调整大小,并且在编译时检查n
,因为它是一个运行时值。你需要重构代码以获得com堆时间错误(例如std/boost static_assert)。我不喜欢这个答案,原因很明显,但它确实满足您的要求:
struct x {
void true_resize(int n) { }
template <int N> void template_resize();
};
template<> void x::template_resize<0>() { true_resize(0); }
template<> void x::template_resize<1>() { true_resize(1); }
template<> void x::template_resize<2>() { true_resize(2); }
template<> void x::template_resize<3>() { true_resize(3); }
#define resize(x) template_resize<x>();
int main () {
x x;
x.resize(2);
x.resize(4);
}
struct x{
void true_resize(int n){}
模板无效模板_resize();
};
模板void x::模板_resize(){true_resize(0);}
模板void x::模板_resize(){true_resize(1);}
模板void x::模板_resize(){true_resize(2);}
模板void x::template_resize(){true_resize(3);}
#定义调整大小(x)模板_resize();
int main(){
x;
x、 调整大小(2);
x、 调整大小(4);
}
<> P> >不明显,<>代码> <代码>不遵守C++范围规则,因此将名称>代码>调整大小< /代码>用于所有其他用途。确实没有任何方式来做到这一点,尤其是只能够用整数文字调用它的部分。您可能不得不放弃并依赖约定。(即,告诉人们不要调用值超出范围的代码)由运行时断言支持。编辑只是将问题从resize
推到ConstructedFromLiteral
的构造函数,即如何使其仅针对特定的文字或常量值进行编译。我刚刚检查了gcc,以查看它是否有一个警告,用于将整型常量表达式转换为超出范围的枚举类型“但是,似乎没有。惭愧。”史提夫说,编辑是对评论的回应,他认为修改大小的方法必须保持停滞。还有,GCC带有墙警告任何从int到EnUM类型的转换,而不是只是超出范围。@马克:啊,是的,C++中没有隐式转换,我在想C.,即使有警告,也不会。help.Oops.我认为您的建议不可能通过以下观察来总结:您不能在值上重载函数,而只能在类型上重载函数。因为您希望匹配resize(n)
,提取有关n
的信息的唯一方法是通过重载解析,但无法提取n
的值。OP显示x.resize(2)仍应按原样编译。
@K-ballo:好的,让我来解决这个问题。谢谢。错误。请重新阅读问题。resize仍应接受一个参数。但我想强制该参数为intliteral@Mark当前位置我在新的开场白中提到了这一点。如果您还有其他问题,请告诉我。顺便说一句,您永远无法区分eral和,比如说,一个静态常量。该语言是关于值的,而不是关于表示。@Kerrek SB:C++11 constexpr实际上允许在使用constexpr值调用时将此类内容作为编译时检查,否则将作为运行时异常。您不能专门化函数模板。错误。请重新阅读问题。resize仍应接受一个argument。但我想强制该参数为int literal。糟糕,你不能部分专门化。这是完全专门化,所以不是问题。你完全没有抓住要点。resize的调用方不应该更改代码,只要他们