gpt4 book ai didi

c++ - 单元测试 : checks that some expressions shouldn't be compiled

转载 作者:太空狗 更新时间:2023-10-29 23:10:49 24 4
gpt4 key购买 nike

在我想检查的单元测试中,某些表达式无法编译。例如,如果我正在编写不可复制的类,我想检查是否无法调用复制构造函数(因此不应编译调用复制构造函数的表达式)。目前我正在使用谷歌测试,没有这种可能性。

众所周知,这可以通过使用 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)));

Live demo

想法是您需要检查的表达式必须依赖于模板参数,但模板参数不需要连接到您需要检查的类型。所以 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com