Reputation: 14464
The draft C++20 standard N4861 sect. 6.5.1(7) reads:
A name used in the definition of a class
X
outside of a complete-class context ofX
shall be declared ... before its use in classX
or be a member of a base class ofX
....
So why does the following compile?
#include <iostream>
struct X {
X(const int i_) : i(i_) {}
int f() const { return 3*g(); }
int g() const { return 2*i; }
const int i;
};
int main()
{
const X x{7};
std::cout << x.f() << "\n";
}
I mean, of course, it should indeed compile, and does, and the output is 42
just as one would expect; but I do not understand the standard's phrasing. The standard says, "before its use," but in the example, isn't g()
declared after its use? And i
, too.
Upvotes: 1
Views: 195
Reputation: 181027
The key part to the paragraph you are quoting is
outside of a complete-class context
Inside a member function body, you are in a complete-class context. This means the rule does not apply.
The full definition for a complete-class contect can be found in [class.mem.general]/7:
A complete-class context of a class (template) is a
- function body ([dcl.fct.def.general]),
- default argument ([dcl.fct.default]),
- default template argument ([temp.param]), noexcept-specifier ([except.spec]), or
- default member initializer
Upvotes: 4
Reputation: 5202
The short answer is that you're not breaking the rule cited.
To my understanding, the key part is "outside of a complete-class context." I see that you use g()
in f()
, and g()
had not formally been declared yet, but it's in the class X
. If g()
were a global function declared and implemented after X
, I think that's where you'd run into an issue. If class X
had a member Y
object, the compiler needs to know all about Y
first so that it can be included. That's what the rule is saying.
Upvotes: 1