是否可以表示不应编译的表达式的静态_assert
Is it possible to express a static_assert for an expression that should not compile?
我想用以下表格表达一个static_assert:
static_assert(expression should not compile);
让我添加一个完整的示例:
template <bool Big>
struct A{};
template <>
struct A<true>
{
void a() {}
};
A<false> b;
static_assert(!compile(b.a()));
or
static_assert(!compile(A<false>::a()));
因此,这个想法是能够确保表达式(带有有效语法)不会编译。
如果解决方案仅使用C 11,就会更好。
好的,考虑到您的问题的上下文有些模糊,此答案可能不适合您的情况。但是,我发现这是一个非常有趣的挑战。
清楚,如评论中所述,该解决方案将必须利用某种(表达)Sfinae。基本上,我们需要的是检测成语的更通用变体。Hovewer,这里主要有两个问题:
1)要使Sfinae启动,我们需要某种模板。
2)要提供compile(XXX)
语法,我们需要在宏中创建这些模板"即时"。否则,我们必须提前为每个测试定义一个测试功能。
第二个约束使事情变得相当困难。我们可以在Lambdas内部定义本地的结构和功能。不幸的是,模板不允许。
所以,这是我能够得到多远(不是100%您想要的,而是相对较近)。
通常,Expression-Sfinae检测器要么利用(模板)功能超载或类模板专业化。由于两者都不允许在lambda内部,因此我们需要一个额外的层:一个函子,该函子占用一堆lambdas,并将其称为最适合呼叫参数的函数。这通常与std::variant
结合使用。
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
现在我们可以创建这样的检测器:
auto detector = overloaded{
[](auto, auto) -> std::false_type {return {};}
,
[](auto x, int)-> decltype(decltype(x)::a(), std::true_type{}){ return {};}
};
static_assert(!detector(A<false>{}, int{}));
static_assert(detector(A<true>{}, int{}));
现在,我们可以定义一个宏,该宏可以定义并调用所需表达式的dector:
#define compile(obj, xpr)
[]() {
auto check =
overloaded{[](auto&&, auto) -> std::false_type { return {}; },
[](auto&& x, int) -> decltype(x xpr, std::true_type{}) {
return {};
}};
return decltype(check(obj, int{})){};
}()
此宏创建一个lambda,将xpr
替换为检测器,并在decltype(x)
上执行类型扣除以使Sfinae启动。可以使用如下:
static_assert(!compile(b, .a()));
static_assert(compile(a, .a()));
int x = 0;
static_assert(compile(x, *= 5));
static_assert(!compile(x, *= "blah"));
不幸的是,它不会与一个类型作为第一个参数。因此,我们需要第二个宏来进行这些AF测试:
#define compile_static(clazz, xpr)
[]() {
auto check = overloaded{
[](auto, auto) -> std::false_type { return {}; },
[](auto x, int) -> decltype(decltype(x) xpr, std::true_type{}) {
return {};
}};
return decltype(check(std::declval<clazz>(), int{})){};
}()
static_assert(!compile_static(A<false>, ::a()));
static_assert(compile_static(A<true>, ::a()));
如上所述,这不是您要求的100%,因为我们始终需要额外的,
来分开宏参数。而且,它需要两个独立的宏。也许这是可以使用预处理器来检测xpr
参数是否以::
开头的障碍。而且,当然,可能在某些情况下不起作用。但是也许这是一个起点。
它需要C 17,但似乎可以与GCC> = 7一起使用,clang> = 5甚至MSVC 19.
这是一个完整的例子。
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- (C++)分析树以计算返回错误值的简单算术表达式
- #为""定义宏;静态";针对不同的上下文
- 非类类型表达式的静态类型与动态类型之间的差异
- 静态强制转换内的表达式
- 常量表达式中的静态成员访问
- 是否可以表示不应编译的表达式的静态_assert
- 使用折叠表达式初始化静态 constexpr 类数据成员不编译
- 如何理解"动态类型:〈prvalue〉静态类型的prvalue表达式PP_7
- 静态之前的预期主要表达式?必须使用常量指针
- 在泛型lambda表达式的所有实例化之间共享的局部静态变量
- 来自另一个类的 switch 语句中的静态 const int 会导致错误 C2051:案例表达式不是常量
- 为什么静态常量成员不能出现在常量表达式中,例如 'switch'
- 在C++03中,在未赋值的上下文中使用表示非静态数据成员的id表达式有效吗
- 奇怪的无符号静态常量不是类模板中的常量表达式
- 为什么静态变量的初始化仅限于常量表达式
- double类型静态类成员的常量表达式初始化项
- 在模板化的using表达式中找不到静态constexpr成员函数
- 用new表达式初始化非静态数据成员
- 静态常量地址不是常量表达式吗?