c++ - 具有条件 constexpr 被调用者的 constexpr 函数

标签 c++

示例代码:

#include <cstdint>

//#define USE_CONSTEXPR_INTRINSICS

#if defined (USE_CONSTEXPR_INTRINSICS)
namespace intrin
{
    [[nodiscard]] constexpr int lsb(std::uint64_t value)
    {
        int r = 0;
        while (value <<= 1) ++r;
        return 63 - r;
    }
}
#else
namespace intrin
{
    [[nodiscard]] inline int lsb(std::uint64_t value)
    {
        return __builtin_ctzll(value);
    }
}
#endif

constexpr int f(std::uint64_t v)
{
    return intrin::lsb(v);
}

#if defined (USE_CONSTEXPR_INTRINSICS)
static_assert(f(13) == 3);
#endif

int main() {}

有一个“内在”函数lsb,我可以有条件地将其编译为 constexpr - 以允许使用 static_assert 进行静态测试(这也是有条件编译的,与 constexpr 内在函数相同)。 问题来自于 f 被标记为 constexpr - 这使得当 lsb 不是 constexpr 时它的格式不正确。 目前我通过

来“解决”这个问题
#if defined (USE_CONSTEXPR_INTRINSICS)
#define INTRIN_CONSTEXPR constexpr
#else
#define INTRIN_CONSTEXPR inline
#endif

然后将 f 声明为

INTRIN_CONSTEXPR int f(std::uint64_t v)

但对我来说这个解决方案并不理想,因为有许多函数使用 lsb,有时非常间接,并且它变得难以跟踪(不需要诊断,所以有时它因编译器而异)并且不合适。我更喜欢的是仅在需要时进行检查 - 例如在 static_assert 周围 - 并且编译器在其他情况下保持沉默。

目前有什么方法可以使其更加自动化吗? future 是否有希望变得更容易?

最佳答案

C++20 通过 std::is_constant_evaluated 使这变得微不足道

[[nodiscard]] constexpr int lsb(std::uint64_t value)
{
    if (std::is_constant_evaluated())
    {
        int r = 0;
        while (value <<= 1) ++r;
            return 63 - r;
    }
    else
    {
         return __builtin_ctzll(value);
    }
}

在 constexpr 上下文中:

static_assert(lsb(1) == 0); // OK

在运行时上下文中:

auto test(int n)
{
    return lsb(n);
}

编译为:

test(int):
        movsx   rax, edi
        rep bsf rax, rax
        ret

请注意,它不是 if constexpr(std::is_constant_evaluated())。这将始终返回 true


对于任何查看此内容的人,为了简洁起见,alg 是不完整的,lsb(0) 应该返回 64

关于c++ - 具有条件 constexpr 被调用者的 constexpr 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57672044/

相关文章:

c++ - 计算函数在代码中被引用的次数

java - 什么数组结构存在于 C# 中,但存在于 C/C++/Java 中?

c++ - Windows服务Win10中的Toast通知

c++ - 检查字符串是否包含数字范围

c++ - 在 C++ 中实现 "AND"和 "OR"时出错

c++ - 是否可以回调模板类的成员?

c++ - std::vector 中的自定义分配器

c++ - Linux 上的文件描述符 3 有什么特别之处?

c++ - 如何使用 boost 多精度生成正态随机数?

c++ - 什么是 CppCheck 的 Windows 等价物?