C++ 这个代码怎么可能是constexpr?(标准:计时)

C++ 这个代码怎么可能是constexpr?(标准:计时),c++,c++14,constexpr,chrono,c++17,C++,C++14,Constexpr,Chrono,C++17,在标准文件P0092R1中,Howard Hinnant写道: template <class To, class Rep, class Period, class = enable_if_t<detail::is_duration<To>{}>> constexpr To floor(const duration<Rep, Period>& d) { To t = duration_cast<To>

在标准文件P0092R1中,Howard Hinnant写道:

template <class To, class Rep, class Period,
          class = enable_if_t<detail::is_duration<To>{}>>
constexpr
To floor(const duration<Rep, Period>& d)
{
    To t = duration_cast<To>(d);
    if (t > d)
        --t;
    return t;
}
但这段代码可以编译,并在编译时给出正确的答案:

static_assert(floor<hours>(minutes{3}).count() == 0, "”);
static_断言(floor(minutes{3}).count()==0,”;

这是怎么回事?

答案是并非编译时例程中的所有操作都必须是constexpr;只有那些在编译时执行的操作

在上面的示例中,操作是:

hours t = duration_cast<hours>(d);
if (t > d) {} // which is false, so execution skips the block
return t;
根据and规则,只要不修改全局可见状态,
constexpr
函数中的表达式本身不必是常量表达式

这里有一个例子

constexpr int f(int a) {
  int n = a;
  ++n;                  // '++n' is not a constant expression
  return n * a;
}
int k = f(4);           // OK, this is a constant expression.
                        // 'n' in 'f' can be modified because its lifetime
                        // began during the evaluation of the expression.
这些很可能是霍华德·希南特在写你提到的论文时遵循的规则


为了处理问题中的
duration
代码,
操作符--
必须被设置为
constexpr
函数。因为
constexpr
对库的更改不是最终的,所以很容易理解Howard是如何依赖于这样的更改的。

对不起,Ben,Marshall的这一更改完全正确你提到的论文是C++14,我最近犯了这个错误,使用C++14.FWIW,霍华德论文的原始版本(P0)可以在这里找到:
static_assert(floor<hours>(minutes{-3}).count() == -1, "”);
error: static_assert expression is not an integral constant expression
        static_assert(floor<hours>(minutes{-3}).count() == -1, "");
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: non-constexpr function 'operator--' cannot be used in a constant expression
                        --t;
                        ^
note: in call to 'floor(minutes{-3})'
        static_assert(floor<hours>(minutes{-3}).count() == -1, "");
template <class To, class Rep, class Period,
          class = enable_if_t<detail::is_duration<To>{}>>
constexpr
To floor(const duration<Rep, Period>& d)
{
    To t = duration_cast<To>(d);
    if (t > d)
        t = t - To{1};
    return t;
}
constexpr int f(int a) {
  int n = a;
  ++n;                  // '++n' is not a constant expression
  return n * a;
}
int k = f(4);           // OK, this is a constant expression.
                        // 'n' in 'f' can be modified because its lifetime
                        // began during the evaluation of the expression.