Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.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++_Templates - Fatal编程技术网

C++ 当且仅当语句未编译时,我是否可以编写成功的测试?

C++ 当且仅当语句未编译时,我是否可以编写成功的测试?,c++,templates,C++,Templates,我想阻止我们班的客户做傻事。为此,我使用了类型系统,并使我的类只接受特定类型作为输入。考虑下面的例子(不是真实的代码,为了示例,我已经放弃了像虚拟析构函数之类的东西): 我不希望有人稍后回来说,“嘿,看!分类器和过滤器有相同的签名。我可以制作一个两者都有的通用签名!”,从而打破语义差异MyClassrequires 这是一种常见的需求吗?如果是的话,我该如何实现它的测试?为什么要等到运行时?编译时检查(例如)可能会使有问题的代码无法编译 但是为了回答你的问题,我相信没有-除非你在测试中运行编译器

我想阻止我们班的客户做傻事。为此,我使用了类型系统,并使我的类只接受特定类型作为输入。考虑下面的例子(不是真实的代码,为了示例,我已经放弃了像虚拟析构函数之类的东西):

我不希望有人稍后回来说,“嘿,看!分类器和过滤器有相同的签名。我可以制作一个两者都有的通用签名!”,从而打破语义差异
MyClass
requires


这是一种常见的需求吗?如果是的话,我该如何实现它的测试?

为什么要等到运行时?编译时检查(例如)可能会使有问题的代码无法编译

但是为了回答你的问题,我相信没有-除非你在测试中运行编译器,否则你不能这样做


但是,请再次查看编译时断言或。没有理由等到测试时才看到这些错误。

要测试预期的编译时失败,您需要在某种具有自动构建功能的框架中运行测试。框架调用编译器从源代码构建,根据预期检查编译返回代码的成功/失败,然后运行生成的tests.exe(如果是运行时测试)


我知道Boost的回归测试中存在这样的特性,尽管我还没有研究它是如何实现的。也许你可以看看那里的例子/想法。

一般来说,没有。如果一条语句没有编译(即不是有效的ISO C++),编译器就不再有义务创建一个可执行文件

有一个著名的例外,它甚至有一个缩写:SFINAE,或者替换失败不是错误。粗略地说,在许多情况下(例如过载解析),编译器将隐式实例化一些模板,以考虑结果。如果编译器尝试一个未能编译的实例化,然后停止整个编译过程,那将是非常烦人的。因此,在这种情况下,它将默默地放弃实例化错误

可以利用此SFINAE机制在编译时确定某些属性。考虑这一点:

template<typename T> class Foo() {
  static char test(T);
  static int test(...);
  static const size_t result = sizeof(test(0));
};
模板类Foo(){
静态炭试验(T);
静态int检验(…);
静态常数size_t result=sizeof(测试(0));
};

现在,如果表达式
T(0)
编译,即如果0可以转换为T,那么Foo::result是sizeof(char)==1,否则Foo::result是sizeof(int)。

根据最新的说明,问题很简单:

void foo(Filter*);
void foo(Sorter*);
template<typename T> void test() {
   foo((T*)NULL);
}
void foo(过滤器*);
void foo(分拣机*);
模板无效测试(){
foo((T*)空);
}

如果有人传递了一个既是过滤器又是分类器的类,重载解析是不明确的。

如果我想断言语句将被编译,那么编译时断言就可以了。然而,断言某些东西不可编译更为困难。我并不特别关心它是编译时还是运行时(我假设它必须是编译时),如果你想禁止编译某些东西,那么正确的做法是通过引入各种编译时检查(如概念检查)使它们无法编译。在运行时这样做太晚了。拉维:问题是,我需要编译项目的其余部分而不会失败。您能否明确说明哪些语句不应该在这里编译?@MSalters:以上所有内容都应该正确编译。不应该编译的是,如果有人试图使用“分类器”,而他们本应该使用“过滤器”。筛选器必须在分类器之前运行,因为没有理由对将要抛出的数据进行排序。因此,基本上filter::SetNext()应该接受分类器参数,但sorter::SetNext()不应该接受筛选器参数?听起来很琐碎,我看不出标题与此有什么关系。@MSalters:是的。我不希望有人稍后回来,看到“Sorter”和“Filter”具有相同的签名,使用自动重构工具使它们成为一种类型,并打破语义检查。听起来你最好还是放弃
Filter
Sorter
是同一类型对象的想法。毕竟,对对象进行两次排序是没有意义的。将可以链接的事物与不能链接的事物分开,并将它们分别添加到您的结构中。然后,在你的
运行
程序中,只需在你的任何过滤器之后运行你的单一分拣机。这可能是可行的。我只需要检查一条语句,就可以用断言检查Foo::result+1.如果我得到有效的东西,我会打勾的。
void foo(Filter*);
void foo(Sorter*);
template<typename T> void test() {
   foo((T*)NULL);
}