- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在我想检查的单元测试中,某些表达式无法编译。例如,如果我正在编写不可复制的类,我想检查是否无法调用复制构造函数(因此不应编译调用复制构造函数的表达式)。目前我正在使用谷歌测试,没有这种可能性。
众所周知,这可以通过使用 SFINAE 来实现。基本思想是,应该测试的表达式应该作为参数传递给 decltype()。表达式的某些部分必须是模板(不使用模板参数编译器会立即指向错误)。现在,如果可以编译表达式,则 decltype() 可以确定表达式的类型,并选择特定的模板(其中写入参数 decltype)。如果无法编译表达式,则将选择其他模板。稍后,在运行时,我们可以分析结果...
这种方法的主要缺点是表达式的一部分应该是模板参数,这导致代码可读性差。我想问的问题是:按原样编写整个表达式而不将其拆分为模板参数和表达式本身的方法在哪里?还有一个问题,是否有可能避免使用 std::declval?
例如,目前我应该写:
COMPILE_TEST(..., T, noncopyable, T(std::declval<T>()));
如果不需要模板参数,我可以这样写:
COMPILE_TEST(..., noncopyable(std::declval<noncopyable>()));
在理想情况下,我想写这样的东西:
COMPILE_TEST(..., { noncopyable t; noncopyable t2(t); });
但我想,这完全不可能。
完整示例(https://coliru.stacked-crooked.com/a/ecbc42e7596bc4dc):
#include <stdio.h>
#include <utility>
#include <vector>
template <typename...> using _can_compile = void;
struct cant_compile { constexpr static bool value = false; };
#if COMPILE_TEST_ASSERTS
#define CAN_COMPILE_ASSERT(val, name, param, decl, ...) \
static_assert(val, "this shoul'd not be compiled (" #name "): " __VA_ARGS__ " [with " #param "=" #decl "]");
#else
#define CAN_COMPILE_ASSERT(name, param, decl, ...) static_assert(true, "")
#endif
#define COMPILE_TEST(name, param, decl, ...) \
template <typename T, typename = void> struct can_compile_##name : public cant_compile {}; \
template <typename T> struct can_compile_##name<T, _can_compile<decltype(__VA_ARGS__)>> { constexpr static bool value = true; }; \
CAN_COMPILE_ASSERT(!can_compile_##name<decl>::value, name, param, decl, #__VA_ARGS__); \
constexpr bool name = can_compile_##name<decl>::value;
struct noncopyable_good
{
noncopyable_good() {}
noncopyable_good(const noncopyable_good&) = delete;
};
struct noncopyable_bad
{
noncopyable_bad() {}
// noncopyable_bad(const noncopyable_bad&) = delete;
};
COMPILE_TEST(good, T, noncopyable_good, T(std::declval<T>()));
COMPILE_TEST(bad, T, noncopyable_bad, T(std::declval<T>()));
int main()
{
printf("noncopyable_good can%s be copied\n", good ? "" : "'t");
printf("noncopyable_bad can%s be copied\n", bad ? "" : "'t");
return 0;
}
类似问题:
最佳答案
这里对您的代码进行了非常细微的修改,消除了额外的参数。
template <class X, class Y>
auto my_declval() -> Y;
#define MY_DECLVAL(...) my_declval<T, __VA_ARGS__>()
template <typename...> using _can_compile = void;
struct cant_compile { constexpr static bool value = false; };
#if COMPILE_TEST_ASSERTS
#define CAN_COMPILE_ASSERT(val, name, decl) \
static_assert(val, "this shoul'd not be compiled (" #name "): " #decl );
#else
#define CAN_COMPILE_ASSERT(name, decl, ...) static_assert(true, "")
#endif
#define COMPILE_TEST(name, ...) \
template <typename T, typename = void> struct can_compile_##name : public cant_compile {}; \
template <typename T> struct can_compile_##name<T, _can_compile<decltype(__VA_ARGS__)>> { constexpr static bool value = true; }; \
CAN_COMPILE_ASSERT(can_compile_##name<void>::value, name, #__VA_ARGS__); \
constexpr bool name = can_compile_##name<void>::value;
struct noncopyable_good
{
noncopyable_good() {}
noncopyable_good(const noncopyable_good&) = delete;
};
struct noncopyable_bad
{
noncopyable_bad() {}
// noncopyable_bad(const noncopyable_bad&) = delete;
};
COMPILE_TEST(good, noncopyable_good(MY_DECLVAL(noncopyable_good)));
COMPILE_TEST(bad, noncopyable_bad(MY_DECLVAL(noncopyable_bad)));
想法是您需要检查的表达式必须依赖于模板参数,但模板参数不需要连接到您需要检查的类型。所以 MY_DECLVAL 是空洞地依赖于一些虚拟参数 T
,而传递的实际参数是 void
(可以是任何类型)。
(我删除了 CAN_COMPILE_ASSERT
调用中的否定,因为我认为它在那里是错误的,并简化了它的定义)。
您需要在要检查的表达式中至少有一个 MY_DECLVAL。
关于c++ - 单元测试 : checks that some expressions shouldn't be compiled,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54689453/
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我是 .NET 框架开发人员的新手。我刚刚通过 IIS 将我的 Web 部署到 Web 服务器中,但遇到了一些问题。我无法登录,需要显示我的数据库表的菜单没有显示。 Error.An error oc
我是 .NET 框架开发人员的新手。我刚刚通过 IIS 将我的 Web 部署到 Web 服务器中,但遇到了一些问题。我无法登录,需要显示我的数据库表的菜单没有显示。 Error.An error oc
这个问题已经有答案了: When is it OK to catch NullPointerException? (10 个回答) 已关闭 4 年前。 请耐心等待,因为我已经阅读了一些相关内容,但我仍
我读过 When should I use a struct instead of a class?其中引用了 MSDN 的指南,其中说: Do not define a structure unle
在接口(interface)中,我有一个方法可以在一个实现中使用,但不应该在另一个实现中使用。如果有人在那个特定的实现中使用那个方法,我正在考虑抛出一个异常。 (这并不是说很容易意外遇到该异常) 更具
我读了很多关于 TDA 以及 getter 和 setter 方法的优缺点的文章,尽管我不一定同意我读到的所有内容,但假设您应该总是告诉而不是询问,并且您应尽可能避免访问器方法,这是否意味着所有方法都
最近我正在更新一些用于使用 GetWindowDC -> CreateCompatibleDC -> CreateCompatibleBitmap -> SelectObject -> BitBlt
我检查了一些其他问题,显然最好的解决方案是首先防止导致此问题的行为,但问题非常间歇性,而且非常不可重现。 我基本上有一个主窗体和子窗体。子表单显示在主表单的菜单和/或按钮中,如下所示: private
From MSDN : If the most significant bit is set, the key is down, and if the least significant bit is
最近我将我的代码从 Express 更改为 Restify。老实说,我不确定以前是否发生过这种情况,但我想确实发生过。 基本上在我的中间件中,我调用了一个 promisified 方法,当它解析时,我
我在 VB.NET 中使用 LINQ,有时我会遇到类似的查询 For i = 0 To 10 Dim num = (From n In numbers Where n Mod i = 0 Sele
我刚刚升级到 Yarn v1.0.2(稳定版),当我执行 yarn install 时,我收到了很多这样的警告: The case-insensitive file shouldn't be copi
我是一名优秀的程序员,十分优秀!