1

I'm implementing a pure virtual function in a C++ derived class, and mark the method final. I would also like to mark the function constexpr, but it appears the standard doesn't allow this.

Is there any practical reason why it would be difficult for compilers to implement this? Or is such a feature omitted due to the usual "this feature wasn't deemed to be important enough to add to the standard" thinking?

Based on the comments, it seems my original question didn't make it clear I am asking about constexpr final functions. The following code illustrates what I am trying to compile:

struct A {
    virtual int foo() const;
};

struct B : public A {
    // Note that this function is final, and is therefore no longer
    // polymorphic in types derived from B (e.g., the function call
    // no longer requires a lookup in the virtual method table
    // when the compile-time type is known to be derived from B)
    constexpr int foo() const final {
        return 0;
    }
};

Note that this was flagged as a duplicate of Can virtual functions be constexpr?, since in C++20, the above code would compile with or without the final keyword.

Jeff G
  • 4,470
  • 2
  • 41
  • 76
  • 2
    Are you compiling in C++20? – Bob__ Jun 24 '21 at 00:19
  • Virtual polymorphism doesn't work at compile time, that would completely defeat it's purpose. If you need static polymorphism, which works with `constexpr` you can still use the good ole CRTP. – πάντα ῥεῖ Jun 24 '21 at 00:22
  • 1
    `virtual` functions are all about the compiler not knowing what the implementation may be. `constexpr` functions are all about the compiler knowing exactly what the implementation is. I don't see what should the result of combining them be. – IS4 Jun 24 '21 at 00:22
  • 1
    Related: https://stackoverflow.com/questions/34828161/can-virtual-functions-be-constexpr – Bob__ Jun 24 '21 at 00:27
  • @Bob__ I'm using VS2017 (15.9.33), which defaults to C++14 but can support up to C++17. Did they add that support in a later revision of the standard? – Jeff G Jun 24 '21 at 00:57
  • @πάνταῥεῖ @IS4 Since the function is flagged as being `final`, it is no longer polymorphic (e.g., the function is no longer logically `virtual`). Therefore, it seems reasonable to have a `constexpr final` function. – Jeff G Jun 24 '21 at 00:58
  • @JaMiT Yes, but in that case the fact the function is `constexpr` isn't known to the compiler. Once a variable is known at compile-time to be type `B` (or any further derived type), it seems useful for the compiler to treat it as a `constexpr` function *in those cases*. True, there is some polymorphism happening, but I wouldn't expect any compile-time known type derived from `B` to have to lookup the address of the method in the virtual function table, since any class thereafter knows exactly which function implementation to use. – Jeff G Jun 24 '21 at 01:13
  • @JaMiT I updated the comment in the code. Does that clear up the ambiguity? – Jeff G Jun 24 '21 at 01:23
  • I see you edited the question. Yes, you're using `final`, unlike the target, but why do you feel that changes the question? – cigien Jun 24 '21 at 01:40
  • @cigien The answer is exactly the opposite in the two cases. Instead of "No, this isn't allowed", the answer to my question is "Yes, this is supported in C++20". To me, that seems like it changes the question. The other question's code example explicitly declares a non-final `constexpr virtual` function, which wouldn't make sense. – Jeff G Jun 24 '21 at 01:43
  • The answers are exactly the same. Are you referring to the accepted answer that says it's not allowed? Note that the first line is bolded and says "This answer is no longer correct as of C++20.". I agree, it's a little unclear. `final` doesn't make any difference; `virtual` functions can be constexpr from C++20, whether they're `final` or not. – cigien Jun 24 '21 at 01:46
  • @cigien I thought the point of asking questions here was to not only help myself, but also help anyone in the future that has the same question. The only place in that entire post where the `final` keyword is mentioned is in a comment, where the commenter indicates it *could* be useful to allow `constexpr final` functions, but doesn't in any way indicate whether such functionality is actually included or planned to be included in any C++ standard. Since my question wasn't answered there, it isn't a duplicate. – Jeff G Jun 24 '21 at 01:52
  • Ok, it looks like we disagree that the questions are duplicates. I really don't see that it's useful to have a separate question for `final`, since it doesn't make a difference. I would close as duplicate a question that changed some other aspect of the function that doesn't make a difference. Still, you're welcome to disagree. You've edited the question to say that it's not a duplicate of the target (though the explanation of *why* is not clear). If other users agree, it'll be reopened. – cigien Jun 24 '21 at 01:57
  • @cigien Oh, I see why you think it is a duplicate now. It appears the `final` keyword isn't even required in C++20 to make my code compile. Odd, I don't really understand how a non-final function could possibly be treated as `constexpr` by the compiler, but OK. At least I finally understand why you flagged it as a duplicate. I'll update the post accordingly. – Jeff G Jun 24 '21 at 01:59
  • @JeffG Yes, that makes your perspective clear (to me at least). – JaMiT Jun 24 '21 at 03:12
  • 1
    @JeffG Regarding: *" Odd, I don't really understand how a non-final function could possibly be treated as `constexpr` by the compiler, but OK."*. Consider the case where an object is **not** accessed through a pointer or reference. Suppose you had declared a variable like `constexpr B obj;` then called `obj.foo();`. In this case, no run-time lookup of the function is necessary, as it is known what the real type of the object is. The call is to `B::foo()`. *On another level, an answer you are looking for probably involves "it's not problematic, so don't complicate the language spec".* – JaMiT Jun 24 '21 at 03:20
  • @JeffG, I'd recommend looking at the [original proposal](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1064r0.html). It really is just having something that works at runtime pre-C++20 work the same way during constant evaluation in C++20. It's not that different from how you can mutate local variables in `constexpr` functions and it conceptually works identically to mutating variables at runtime, but the variables are (traditionally) all part of the compiler's constexpr interpreter. – chris Jun 24 '21 at 05:05

1 Answers1

2
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173