如何验证某些模板 *not* 为给定的参数类型编译?

Posted

技术标签:

【中文标题】如何验证某些模板 *not* 为给定的参数类型编译?【英文标题】:How to validate that some template does *not* compile for given argument types? 【发布时间】:2009-05-12 22:22:43 【问题描述】:

我正在编写一个智能 ptr 模板,该模板仅针对给定的基类及其子类进行实例化,它提供了类似于 boost::shared_ptr 的隐式转换到模板 MyPtr<U> 的变体 MyPtr<T> 很长因为从 T* 到 U* 的转换是有效的(有效的基类和 const 兼容)。

这在 vs2005 中运行良好,但不适用于 g++ 在 linux 上,所以我的同事在那里更改了它,但这样做破坏了 const 正确性。

我的问题是我想对某些转换无效(例如将MyPtr<const T> 分配给MyPtr<T>)进行单元测试,导致文件无法编译!但是您不能在解决方案中没有未编译的文件...

如果有一些特定于 VS 的 #pragma 或一些可以测试给定构造的 SFINAE 技巧NOT有效,因此无法编译?

谢谢,--DD

【问题讨论】:

你能发布一些损坏的代码吗? 你可以查看我问过的关于单元测试编译时错误的这个问题:***.com/questions/605915/unit-test-compile-time-error 感谢卢克的链接。这确实与我的问题具有相同的精神。但答案也让我想要更好的东西。我有一种感觉,如果不打算编译的代码被包装在模板中,那么 SFINAE 可能会有所帮助,该模板稍后用于函数重载解决方案。在此代码中允许不为一个重载候选者编译,而是选择默认情况重载,并且在运行时可检测到。当我有时间时,我会尝试这些方面的东西。 【参考方案1】:

您可以运行命令行编译器cl,它很容易设置,并捕获其错误消息输出。

没有生成文件,也几乎没有来自解决方案/项目的任何信息。只是包含路径和源文件。最简单的是,您只需要一个“反转”另一个程序的退出代码的程序:

#include <sstream>
#include <stdlib.h>

int main(int argc, char *argv[])

    std::ostringstream command;

    for (int n = 1; n < argc; n++)
        command << argv[n] << " ";

    return (system(command.str().c_str()) == EXIT_SUCCESS)
                ? EXIT_FAILURE : EXIT_SUCCESS;

它只是简单地将传递给它的参数重组为(省略其自己的名称)并退出生成的命令行,然后如果失败则返回成功,如果成功则返回失败。这足以欺骗 Visual Studio 或 make

从技术上讲,重新构建的命令行应该引用参数,但只有当你足够疯狂地在构建目录或源文件名中放置空格时才需要!

【讨论】:

我正在寻找在visual studio中运行的东西,这与解决方案中的人民币我的单元测试项目没有什么不同,选择“设置为启动项目”并按F5。拥有可以复制解决方案中所有构建信息的外部脚本/makefile 并不是我真正想到的那种解决方案,并且在发生故障时的报告也可能是外部的。 您似乎在想象这将比实际上更难!请参阅更新的答案。真的很简单(比写一个智能指针简单多了)。 我宁愿写智能 ptr 代码(好吧,实际上我宁愿使用 Boost 的,但这是一个特例,它实际上使用了一个 shared_ptr 内部)宁愿尝试写一个跨平台编译器分叉、输出解析、可与 VS 和 GCC/make 一起使用的程序 ;-) 这太过分了。输出只是退出代码。据我所知,这是一个完全微不足道的问题。我已经用必要的代码更新了答案。【参考方案2】:

如果给定的参数(在您的情况下为“const T”)将满足所有其他单元测试,除了您正在寻找的这个,这不是表明它是一个完全可以接受的情况吗? 换句话说,如果它有效,为什么要禁止它?

【讨论】:

呃。不 ;-) 如果你有一个 boost::shared_ptr,你不能将它隐式转换为 boost::shared_ptr<:string>,出于同样的原因 C++ 禁止对 raw 进行相同的转换指针。我的情况类似,尽管更复杂,因为我的智能指针需要使用 boost::mpl 来决定哪个 T 进入 shared_ptr (因此这个 bug,mpl 并不容易)。

以上是关于如何验证某些模板 *not* 为给定的参数类型编译?的主要内容,如果未能解决你的问题,请参考以下文章

给定传递给它的参数类型,如何确定函数参数的类型?

如何自定义模板以不包含某些类型[重复]

如何检查是不是可以从给定类型构造模板类型

模板函数总结

如何在可变参数类模板中获取类型的索引?

C++模板详解:泛型编程模板原理非类型模板参数模板特化分离编译