14

For this code:

struct S
{
    S(int m): m(m) {}
    constexpr int f() const { return m; }

    int m;
};

int main() { S s(1); }

it is compiled with no warnings or errors by clang 3.6, 3.7 and 3.8 with -std=c++14. But in g++ 5.x the following errors occur:

main.cpp:4:19: error: enclosing class of constexpr non-static member function 'int S::f() const' is not a literal type
     constexpr int f() const { return m; }
               ^
main.cpp:1:8: note: 'S' is not literal because:
 struct S
        ^
main.cpp:1:8: note:   'S' is not an aggregate, does not have a trivial default constructor, and has no constexpr constructor that is not a copy or move constructor

Which compiler is correct and why?

I looked at the requirements in C++14 [dcl.constexpr]/3 which says that for a constexpr function "each of its parameter types shall be a literal type", but that section does not explicitly mention member functions, and does not say whether the implied *this counts as a parameter for the purposes of this clause.

4
  • I doubt that such a member function could be actually useful, because it definitely can't be calculated in compile-time, isn't it? So I would say, gcc diagnostics is more correct. Commented Apr 8, 2016 at 0:24
  • To make sure I just tried a trunk GCC build and it's still broken. Commented Apr 8, 2016 at 0:49
  • @user657267 OK. Perhaps it's not a high priority; as user3159253 points out, this code is not very useful because the evaluation of f() will actually be non-constexpr, even in clang, because S is not a literal type (so constexpr S s(1); is not allowed). Commented Apr 8, 2016 at 0:52
  • @M.M I can see only one use case to allow constexpr on non-static member function of non-literal type. It's generic code when template class can be literal or non-literal depending on template parameters. Commented Apr 8, 2016 at 11:51

1 Answer 1

12

It's a core defect that was fixed for C++14

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1684

Clang was patched

https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/6jM8M8FUs30

There's a tracker for GCC but it doesn't look like anyone has addressed it yet

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66297

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

6 Comments

Isn't this applied only to static member functions?
The comments on the DR suggest that the previous behaviour was intended for non-static member and this change was intended to fix static member... but the actual change appears to apply to both. The plot thickens?
In fact the mailing list link explains that the committee decided to remove it intentionally for non-static too, in a change from what the DR originally recommended
@user3159253 Well the DR comment only mentions static functions but the wording of the fix applies to non-static functions too, as M.M mentions this was ultimately intended, ironically it looks like the DR might have introduced another defect itself if they hadn't.
For info: this was fixed in gcc 7.2, approx August 2017 (see gcc.gnu.org/viewcvs/gcc?view=revision&revision=248752)
|

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.