首页 > 解决方案 > C++ 检查语句是否可以评估 constexpr

问题描述

有没有一种方法可以决定是否可以对某些东西进行 constexpr 评估,并将结果用作 constexpr 布尔值?我的简化用例如下:

template <typename base>
class derived
{
    template<size_t size>
    void do_stuff() { (...) }

    void do_stuff(size_t size) { (...) }
public:
    void execute()
    {
        if constexpr(is_constexpr(base::get_data())
        {
            do_stuff<base::get_data()>();
        }
        else
        {
            do_stuff(base::get_data());
        }
    }
}

我的目标是 C++2a。

我找到了以下 reddit 线程,但我不是宏的忠实粉丝。https://www.reddit.com/r/cpp/comments/7c208c/is_constexpr_a_macro_that_check_if_an_expression/

标签: c++template-meta-programmingconstexprc++20if-constexpr

解决方案


这是另一种解决方案,它更通用(适用于任何表达式,无需每次定义单独的模板)。

该解决方案利用 (1) 从 C++17 开始 lambda 表达式可以是 constexpr (2) 从 C++20 开始,无捕获 lambda 的类型是默认可构造的。

true这个想法是,当且仅当可以出现在模板参数中时才选择返回的重载Lambda{}(),这实际上要求 lambda 调用是一个常量表达式。

template<class Lambda, int=(Lambda{}(), 0)>
constexpr bool is_constexpr(Lambda) { return true; }
constexpr bool is_constexpr(...) { return false; }

template <typename base>
class derived
{
    // ...

    void execute()
    {
        if constexpr(is_constexpr([]{ base::get_data(); }))
            do_stuff<base::get_data()>();
        else
            do_stuff(base::get_data());
    }
}

推荐阅读