gpt4 book ai didi

c++ - 尽可能在编译时强制执行函数契约

转载 作者:IT老高 更新时间:2023-10-28 23:01:49 25 4
gpt4 key购买 nike

(这个问题的灵感来自 How can I generate a compilation error to prevent certain VALUE (not type) to go into the function?)

假设我们有一个单参数 foo,语义上定义为

int foo(int arg) {
int* parg;
if (arg != 5) {
parg = &arg;
}

return *parg;
}

上面的整个代码用于说明一个简单的想法 - 函数返回它自己的参数,除非参数等于 5,在这种情况下行为是未定义的。

现在,挑战 - 以这样的方式修改函数,如果它的参数在编译时已知,则应该生成编译器诊断(警告或错误),如果不是,则行为在运行时保持未定义。解决方案可以依赖于编译器,只要它在四大编译器之一中可用。

以下是一些无法解决问题的潜在路线:

  • 使函数成为模板,将其参数作为模板参数 - 这并不能解决问题,因为它使函数不符合运行时参数的条件
  • 使函数成为 constexpr - 这并不能解决问题,因为即使编译器看到未定义的行为,它们也不会在我的测试中产生诊断 - 相反,gcc 会插入 ud2 指令,这不是我想要的。

最佳答案

constexpr 出现错误当在常量表达式中用于:

constexpr int foo(int arg) {
int* parg = nullptr;
if (arg != 5) {
parg = &arg;
}
return *parg;
}

Demo

我们无法知道参数值在编译类型中是已知的,但我们可以使用类型表示值与 std::integral_constant

// alias to shorten name. 
template <int N>
using int_c = std::integral_constant<int, N>;

可能与 UDLoperator "" _c拥有5_c , 42_c .

然后,添加重载:

template <int N>
constexpr auto foo(int_c<N>) {
return int_c<foo(N)>{};
}

所以:

foo(int_c<42>{}); // OK
foo(int_c<5>{}); // Fail to compile

// and with previous constexpr:
foo(5); // Runtime error, No compile time diagnostic
constexpr auto r = foo(5); // Fail to compile

正如我所说,参数在函数内部不知道是恒定的, is_constexpr seems not possible in standard允许调度,但是一些编译器为此提供了内置的( __builtin_constant_p ),所以使用 MACRO,我们可以进行调度:

#define FOO(X) [&](){ \
if constexpr (__builtin_constant_p(X)) {\
return foo(int_c<__builtin_constant_p (X) ? X : 0>{});\
} else {\
return foo(X); \
} \
}()

Demo

注意:不能使用 foo(int_c<X>{})直接,即使在 if constexpr 中,仍然有一些语法检查。

关于c++ - 尽可能在编译时强制执行函数契约,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53933634/

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