3

If a non-literal class type has no constexpr constructor (it is not constexpr constructible), does a non-static constexpr member function make any sense? I mean if you cannot construct the object at compile time, how would you able to use its member functions?

Anyway, the major compilers don't complain about it, which makes me think it is allowed by the standard.

Nevertheless, you are able to use such constexpr member functions in runtime without any problem. The only question now what is the effect of constexpr in this case, if any. My best guess is that the return value of the constexpr member is being evaluated at compile-time (if possible), so on a run-time call it have to do a simple copy.

Is my guess correct, or is the constexpr specifier absolutely meaningless in this case (i.e. the member function is being evaluated at runtime)?

9
  • 1
    I don't know much about constexpr, but your premise and guess both sound reasonable to me. Commented Oct 29, 2016 at 19:01
  • 1
    You may want to reword your question to focus on non-literal class types. Aggregates, for instance, don't have constexpr constructors but it would make sense for those to have constexpr member functions. Commented Oct 29, 2016 at 19:32
  • In the same way, if you provide only private constructors (without any kind of factory), You won't be able to use non-static public methods. Commented Oct 29, 2016 at 22:51
  • @Jarod42 You are able to use such constexpr defined functions in runtime, but it's not clear what is the expected effect of constexpr in this case, if any. Commented Oct 29, 2016 at 23:08
  • 1
    Your bold text is still true if you take out the word constexpr. Commented Oct 30, 2016 at 0:16

1 Answer 1

1

The premise of your question seems to be that only constexpr functions can be evaluated at compile-time.

This premise is incorrect. The compiler can precompute anything it can figure out a way to do, as long as the exact side result and side-effects are produced (as-if rule).

What constexpr provides is a guarantee that certain expressions will be evaluated at compile-time by every compiler (it's not a "quality of implementation" issue), which makes it possible to use them in contexts where a compile-time value is needed, such as non-type template arguments, operands of case clauses in switch statements, etc.

The specific details around constexpr functions include that there has to be at least one set of arguments (the target instance is an implied argument) such that the constexpr evaluation rules are met. If that isn't true, your program is ill-formed and its runtime behavior is not specified at all, so don't go adding constexpr where it doesn't logically belong.

However, compilers aren't required to diagnose violations of this rule. That means that "major compilers don't complain about it" should not be in any way interpreted as assurance that the code is correct.


Standard's wording, section 7.1.5 (draft n4582)

For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression, or, for a constructor, a constant initializer for some object, the program is ill-formed; no diagnostic required.

Sign up to request clarification or add additional context in comments.

6 Comments

My question didn't assume that only constexpr functions can be evaluated at compile time.
Does this mean that template <typename T> struct A { constexpr T val() { return T(0); } }; and template <typename T> struct A { static constexpr T val() { return T(0); } }; are (1st without, 2nd with static) also ill-formed? I had no problems with such functions yet.
@plasmacel: Those are fine for two reasons: (1) template functions are exempted from the rule, (2) there are no operations executed during the evaluation of those functions that are disallowed during constexpr processing.
@plasmacel: Here's a better example: struct S { int i; S(j) : i{j} {} constexpr int foo() { return i; } constexpr int bar(int k) { return k? i: 0; } }; in which foo is ill-formed but bar is legal, since o.bar(0); won't reach any forbidden operations.
@plasmacel: Also, the two types in your comment are literal types, so they have nothing to do with your question.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.