c++ - 如何确保在运行时永远不会调用 constexpr 函数?

标签 c++ constexpr

假设您有一个函数可以为您的应用程序生成一些安全 token ,例如一些哈希盐,或者可能是对称或非对称 key 。

现在假设您在 C++ 中有这个函数作为 constexpr,并且您根据一些信息(如内部版本号、时间戳等)为构建生成 key 。

你是一个勤奋的程序员,确保并以适当的方式调用它,以确保它只在编译时被调用,因此死剥离器会从最终的可执行文件中删除代码。

但是,您永远无法确定其他人不会以不安全的方式调用它,或者编译器可能不会删除该函数,然后您的安全 token 算法将成为公众知识,使攻击者更容易猜测 future 的 token 。

或者,抛开安全性不谈,假设该函数需要很长时间才能执行,并且您希望确保它在运行时不会发生,并且不会给最终用户带来糟糕的用户体验。

有什么方法可以确保永远不会在运行时调用 constexpr 函数?或者,在运行时抛出一个断言或类似的东西是可以的,但显然不如编译错误那么理想。

我听说有一些方法涉及抛出一个不存在的异常类型,所以如果 constexpr 函数没有被删除,你会得到一个链接器错误,但听说这只适用于一些编译器。

相关问题:Force constexpr to be evaluated at compile time

最佳答案

在 C++20 中,您只需将 constexpr 替换为 consteval 即可强制函数始终在编译时进行评估。

例子:

          int    rt_function(int v){ return v; }
constexpr int rt_ct_function(int v){ return v; }
consteval int    ct_function(int v){ return v; }

int main(){
    constexpr int ct_value = 1; // compile value
    int           rt_value = 2; // runtime value

    int a = rt_function(ct_value);
    int b = rt_ct_function(ct_value);
    int c = ct_function(ct_value);

    int d = rt_function(rt_value);
    int e = rt_ct_function(rt_value);
    int f = ct_function(rt_value); // ERROR: runtime value

    constexpr int g = rt_function(ct_value); // ERROR: runtime function
    constexpr int h = rt_ct_function(ct_value);
    constexpr int i = ct_function(ct_value);
}

C++20 之前的解决方法

您可以强制在常量表达式中使用它:

#include<utility>

template<typename T, T V>
constexpr auto ct() { return V; }

template<typename T>
constexpr auto func() {
    return ct<decltype(std::declval<T>().value()), T{}.value()>();
}

template<typename T>
struct S {
    constexpr S() {}
    constexpr T value() { return T{}; }
};

template<typename T>
struct U {
    U() {}
    T value() { return T{}; }
};

int main() {
    func<S<int>>();
    // won't work
    //func<U<int>>();
}

通过将函数的结果用作模板参数,如果在编译时无法解决,则会出现错误。

关于c++ - 如何确保在运行时永远不会调用 constexpr 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39650122/

相关文章:

c++ - 是否有 strstr() 的 constexpr 版本?

c++ - GCC 接受 `constexpr struct {} s;` 但 Clang 拒绝它。谁是正确的?

c++ - 是否可以将 GTK+ 与 C++ 一起使用?

c++ - 检查已删除对象的值

c++ - 编写一个通用的遍历函数,允许灵活地处理具有不同参数的多个函数

c++ - 如何用C++编辑文本文件数据

c++11 - 自身递归需要的静态 constexpr 模板数组成员

c++ - 可以存储在 float 中的最大连续整数的定义常量?

c++ - 保持函数参数的 consteval-ness

c++ - 三元运算符可以抛出异常吗?