В модульных тестах я хочу проверить, что некоторые выражения не могут быть скомпилированы.Например, если я пишу не копируемый класс, я хочу проверить, что конструктор копирования не может быть вызван (поэтому выражение, которое вызывает конструктор копирования, не должно компилироваться).В настоящее время я использую тест Google, который не имеет такой возможности.
Известно, что это можно сделать с помощью 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;
}
Подобные вопросы: