有没有可能知道何时constexpr真的是一个constexpr?

由于constexpr的扩展版本(我认为是C ++ 14),你可以声明constexpr函数,它可以用作“真正的”constexpr,也就是说,代码可以在编译时执行,或者可以表现为内联函数。 所以什么时候可以有这个程序:

#include <iostream>

constexpr int foo(const int s) {
  return s + 4;
}

int main()
{
    std::cout << foo(3) << std::endl;
    const int bar = 3;
    std::cout << foo(bar) << std::endl;
    constexpr int a = 3;
    std::cout << foo(a) << std::endl;

    return 0;
}

当然,结果是:

7
7
7

到现在为止还挺好。 所以我的问题是:如果函数在编译时或运行时执行,有没有一种方法(可能是标准的)知道foo(const int s)?

编辑:也有可能在运行时知道在编译时是否评估函数?


列出的技术是可行的,但由于它使用static_assert所以它不是友好的。 一个更好的方法(理论上你会明白我的意思)来检查函数是否为noexcept 。 为什么? 因为常量表达式总是不被接受,即使函数没有被标记为这样。 所以,请考虑以下代码:

template <class T>
constexpr void test_helper(T&& t) {}

#define IS_CONSTEXPR(...) noexcept(test_helper(__VA_ARGS__))

test_helperconstexpr ,所以只要它的参数是一个常量表达式。 如果它是一个常量表达式,它将是noexcept ,否则它不会是(因为它没有被标记为这样)。

现在让我们来定义这个:

double bar(double x) { return x; }

constexpr double foo(double x, bool b) {
    if (b) return x; 
    else return bar(x);
}

如果x是一个常量表达式,则foo只有noexcept ,而b是true; 如果布尔值为假,那么我们称之为非constexpr函数,破坏我们的constexpr- ness。 所以,我们来测试一下:

double d = 0.0;

constexpr auto x = IS_CONSTEXPR(foo(3.0, true));
constexpr auto y = IS_CONSTEXPR(foo(3.0, false));
constexpr auto z = IS_CONSTEXPR(foo(d, true));

std::cerr << x << y << z;

它编译,太棒了! 例如,这给了我们编译时布尔(不编译失败),可以用于sfinae。

赶上? 那么,铿有一个多年的错误,并没有正确处理。 但是,海湾合作委员会呢。 现场示例:http://coliru.stacked-crooked.com/a/e7b037932c358149。 它打印“100”,因为它应该。


我认为执行该操作的规范方法是使用static_assertstatic_assert在编译时被评估,所以如果它们的条件为false,它们将破坏构建。

#include <iostream>

constexpr int foo(const int s) {
  return s + 4;
}

int main()
{
    std::cout << foo(3) << std::endl;
    const int bar = 3;
    std::cout << foo(bar) << std::endl;
    constexpr int a = 3;
    std::cout << foo(a) << std::endl;

    static_assert(foo(3) == 7, "Literal failed");
    static_assert(foo(bar) == 7, "const int failed");
    static_assert(foo(a) == 7, "constexpr int failed");
    return 0;
}

clang++ -std=c++14 so1.cpp适合我编译,显示一切正常。


在一个constexpr函数中,你不能判断你是否正在一个constexpr上下文中进行评估。 已经有许多建议来添加这个功能。 没有成功。


constexpr函数外部,有很多方法可以确定是否在constexpr上下文中调用具有特定参数集的函数。 最简单的方法是在需要constexpr的上下文中使用结果。

假设你的constexpr表达式返回一个非空的整数或指针类型(包括函数指针):

#define CONSTEXPR_EVAL(...) 
  std::integral_constant< 
    std::decay_t<decltype(__VA_ARGS__)>, 
    __VA_ARGS__ 
  >::value

那么如果在编译时不能计算bar(foo, true) ,并且如果可以在编译时计算它,它将返回该值CONSTEXPR_EVAL( bar(foo, true) )那么CONSTEXPR_EVAL( bar(foo, true) )将无法编译。

涉及noexcept其他技巧(在编译时评估的函数是noexcept )可以工作(请参阅@NirFriedman的答案)。

链接地址: http://www.djcxy.com/p/68371.html

上一篇: Is it possible to know when is constexpr really a constexpr?

下一篇: Switch in constexpr function