Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我怎样才能强制使用c++;类方法以仅接受少数整数文本?_C++_Templates_Standards - Fatal编程技术网

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的调用方不应该更改代码,只要他们