我想实现my_static_assert与c ++ 17单参数稍有不同的方法static_assert:如果在编译时my_static_assert 不知道里面的条件,则应该通过。
my_static_assert以下示例中的第二个应该通过,但是如果我使用static_assert它将会失败。
#include <iostream>
int x, y;
constexpr int f1() { return 0; }
constexpr int f2() { return 0; }
int f3() { return x; }
int f4() { return y; }
constexpr int sum(int a, int b) { return a + b; }
int main() {
std::cin >> x >> y;
// it should fail
my_static_assert(sum(sum(f1(), f2()), sum(f1(), f1())) != 0);
// it should pass
my_static_assert(sum(sum(f1(), f2()), sum(f4(), sum(f3(), f1()))) != 0);
}
Run Code Online (Sandbox Code Playgroud)
如果您想知道为什么会出现此问题:
我正在使用叶函数f1,f2,f3,f4和表达式节点上的运算来构建表达式:sum,mul,div,sub。在编译时已知的叶子包含始终为0的值。
我正在尝试检查我的表达式是否包含至少一个在编译时未知的元素。
如果您愿意使用具有GNU扩展名的编译器,则可以。所以要当心。
它需要两个重载和一个辅助宏:
template<std::size_t N>
constexpr void assert_helpr(int(&)[N]) = delete;
void assert_helpr(...) {}
#define my_static_assert(...) do { \
__extension__ int _tmp [(__VA_ARGS__) + 1]; \
assert_helpr(_tmp); \
} while(0)
Run Code Online (Sandbox Code Playgroud)
其工作方式如下:
我还没有对它进行彻底的测试,但是它似乎在Clang和GCC上都可以使用。现场观看。
@Artyer很友善地分享了基于此方法的Godbolt解决方案。
这是该代码对这个问题的简化:
template<std::size_t N>
constexpr std::false_type assert_helpr(int(&)[N]);
constexpr std::true_type assert_helpr(...);
#define my_static_assert(...) do { \
__extension__ int _tmp[(__VA_ARGS__) + 1]; \
static_assert(decltype(assert_helpr(_tmp)){}, #__VA_ARGS__); \
} while(0)
Run Code Online (Sandbox Code Playgroud)
重载的用法相同,除了这次我们从通过调用获取实际的结果类型decltype,然后继续从中创建一个真正的编译时布尔常量。
这允许直接使用static_assert,作为一个不错的功能,我们可以将其传递给字符串化的令牌汤,以指示失败的表达式错误。
| 归档时间: |
|
| 查看次数: |
219 次 |
| 最近记录: |