Why does the C++ compiler makes it possible to declare a function as constexpr, which can not be constexpr?

前端 未结 3 1537
醉梦人生
醉梦人生 2020-12-21 04:00

Why does the C++ compiler makes it possible to declare a function as constexpr, which can not be constexpr?

For example: http://melpon.org/wandbox/permlink/AGwniRNRb

3条回答
  •  没有蜡笔的小新
    2020-12-21 05:01

    Let's go straight from it's proposal, www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf in section 4.1, third paragraph: and I quote:

    A constant-expression function may be called with non-constant expressions, in that case there is no requirement that the resulting value be evaluated at compile time.

    See this question: When does a constexpr function get evaluated at compile time?

    template
    T constexpr reduce(Functor f, std::initializer_list il) {
      return std::accumulate(std::next(il.begin()), il.end(), *(il.begin()), f);
    }
    

    Again, as you know, std::accumulate isn't a constexpr function.

    template
    void print_constexpr() { std::cout << value << std::endl; }
    

    Again, as you know, non-type template arguments must be constant expressions.


    Now:

    template
    T constexpr reduce(Functor f, std::initializer_list il) {
      return std::accumulate(std::next(il.begin()), il.end(), *(il.begin()), f);
    }
    

    As to why it works: Here's what the C++ standard has to say:

    [dcl.constexpr/6] (emphasis mine):

    If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is still a constexpr function or constexpr constructor, even though a call to such a function cannot appear in a constant expression ...

    Note: that

    A function instantiated from a function template is called a function template specialization;


    When its not a template, it will fail:

    int constexpr reduce(int(*f)(int, int), std::initializer_list il) {
      return std::accumulate(std::next(il.begin()), il.end(), *(il.begin()), f);
    }
    

    The compiler will complain now that you cannot call a non-constexpr function in a function defined as constexpr

提交回复
热议问题