At https://www.studytonight.com/cpp/inline-functions.php they are explaining inline functions
All the inline functions are evaluated by the compiler, at the end of class declaration.
class ForwardReference
{
int i;
public:
// call to undeclared function
int f()
{
return g()+10;
}
int g()
{
return i;
}
};
int main()
{
ForwardReference fr;
fr.f();
}
At the end they say :
"You must be thinking that this will lead to compile time error, but in this case it will work, because no inline function in a class is evaluated until the closing braces of class declaration."
......
why should one expect a compile time error? is it because no value for i has been set? If so, could someone explain better why it works, I don't get what's the point here, if the member functions are inline or not wouldn't it work the same?
The book is explicitly pointing out to you "no inline function in a class is evaluated until the closing braces of class declaration". Outside of a class declaration, with ordinary functions, this fails:
int f()
{
return g()+10;
}
int g()
{
return 0;
}
Try to compile a C++ source file containing just this, and nothing more, and see for yourself.
In C++, all functions must be declared before use. Since g() is not declared, this is ill-formed and your compiler will reject it. g() must be declared before it's referenced:
int g();
int f()
{
return g()+10;
}
int g()
{
return 0;
}
This does not applly to inline class method because, as your book explains, they are effectively evaluated when the class declaration is complete. At that point both f() and g() methods are declared, and the reference from f() to g() is well-formed.
What they are hinting at here, for why someone might expect a compile error, is the fact that although g is written below/after f, f can still reference it with no error.
If you were to move them out of the class and define+declare them at the same time then you would see the compile error (since f cannot see any g).
i.e.
int f(){
return g() + 10;
}
int g(){
return 32;
}
int main(){
return f();
}
See for yourself on compiler explorer.
Related
Is there a nice way to have a non static value as default argument in a function? I've seen some older responses to the same question which always end up in explicitly writing out the overload. Is this still necessary in C++17?
What I'd like to do is do something akin to
class C {
const int N; //Initialized in constructor
void foo(int x = this->N){
//do something
}
}
instead of having to write
class C {
const int N; //Initialized in constructor
void foo(){
foo(N);
}
void foo(int x){
//do something
}
}
which makes the purpose of the overload less obvious.
One relatively elegant way (in my opinion) would be to use std::optional to accept the argument, and if no argument was provided, use the default from the object:
class C {
const int N_; // Initialized in constructor
public:
C(int x) :N_(x) {}
void foo(std::optional<int> x = std::nullopt) {
std::cout << x.value_or(N_) << std::endl;
}
};
int main() {
C c(7);
c.foo();
c.foo(0);
}
You can find the full explanation of what works/doesn't work in section 11.3.6 of the standard. Subsection 9 describes member access (excerpt):
A non-static member shall not appear in a default argument unless it
appears as the id-expressionof a class member access expression
(8.5.1.5) or unless it is used to form a pointer to member
(8.5.2.1).[Example:The declaration of X::mem1()in the following example
is ill-formed because no object is supplied for the non-static
memberX::a used as an initializer.
int b;
class X {
int a;
int mem1(int i = a);// error: non-static memberaused as default argument
int mem2(int i = b);// OK; useX::b
static int b;
};
I am using g++4.8.0, which doesn't contain earlier constexpr bug. Thus below code works fine:
constexpr int size() { return 5; }
int array[size()];
int main () {}
However, if I enclose both the variable inside a class as static, then it gives compiler error:
struct X {
constexpr static int size() { return 5; }
static const int array[size()];
};
int main () {}
Here is the error:
error: size of array ‘array’ is not an integral constant-expression
Is it forbidden to use constexpr in such a way or yet another g++ bug?
Yes, it is ill-formed. Here's why:
A constexpr function needs to be defined (not just declared) before being used in a constant expression.
So for example:
constexpr int f(); // declare f
constexpr int x = f(); // use f - ILLEGAL, f not defined
constexpr int f() { return 5; } // define f, too late
function definitions inside a class specifier (as well as initializers and default parameters) are essentially parsed in an order like they were defined outside the class.
So this:
struct X {
constexpr static int size() { return 5; }
static const int array[size()];
};
Is parsed in this order:
struct X {
constexpr inline static int size(); // function body defered
static const int array[size()]; // <--- POINT A
};
constexpr inline int X::size() { return 5; }
That is, parsing of function bodies are defered until after the class specifier.
The purpose of this deferral of function body parsing is so that function bodies can forward reference class members not yet declared at that point, and also so they can use their own class as a complete type:
struct X
{
void f() { T t; /* OK */ }
typedef int T;
};
Compared to at namespace scope:
void f() { T t; /* error, T not declared */ }
typedef int T;
At POINT A, the compiler doesn't have the definition of size() yet, so it can't call it. For compile-time performance constexpr functions need to be defined ahead of their use in the translation unit before being called during compile, otherwise the compiler would have to make a multiple passes just to "link" constant expressions for evaluation.
Apparently it's not even a bug, because its status is RESOLVED INVALID, which means that the people behind GCC and that bugzilla, after reviewing the problem, don't think that this is a GCC bug.
I remind you on that page because there is also an answer for this behaviour in one of the related posts.
I just wanted to add that even though this may not be good practice and will restrict you to defining the class body in the same compilation unit that its declared, it's possible to force the compiler to compile the definition of the function bodies at the same point as its declaration by adding a redundant template parameter:
template <typename = void>
struct X {
constexpr static int size() { return 5; }
static const int array[size()];
};
int main()
{
X<> x{};
...
}
The following question is part of the C++ Test on Upwork.
class A {
typedef int I; // private member
I f();
friend I g(I);
static I x;
};
which of the following are valid:
1) A::I A::f() { return 0; }
2) A::I g(A::I p = A::x);
3) A::I g(A::I p) { return 0; }
4) A::I A::x = 0;
Seems to me that all answers are valid. I tested them and they work just fine!
Am I right? or Am I missing something?
The way it's written, all 4 are valid.
This is trivial; it's the definition of the class member function.
This is a function prototype for a function g. Requires the friend declaration, which you have. Otherwise neither I nor the default value x are accessible to the function g.
This is the definition of the function g. Requires the friend declaration, which you have, else I is not accessible to the function g.
This is trivial; it's the definition of the static member x.
I see this code and I can't understand what it mean.
I know how we use default constructor but this is not default constructor. What is this?
class X
{
...
};
int main()
{
X f();
}
It declares a function f which takes no parameters and returns a type X.
This is also known as Most Vexing Parse in C++. It is a byproduct of the way the C++ standard defines the interpretation rules for declarations.
Assume you declare a function:
int Random();
And use it:
int main()
{
int n;
n = Random();
}
But implement the Random function after main. Or assume that Random function is defined in some header. You need to instruct the compiler that Random is a function implemented in some other source file, or in some library.
Therefore, an expression like:
T foo();
Would always mean a instruction to compiler that there is a function named foo which returns T. It cannot be an object of type T.
Its function declaration of name f
X f();
^ ^ function
return type
function f() takes no arguments and returns a X class object.
for example its definition can be like:
class X{
int i;
// other definition
}
X f(){
X x;
// some more code
return x;
}
In main you can use like:
int main(){
X a = f();
int i = f().i;
}
This is a function which doesn't take any argument and returns an object of class X
While I would assume that in VC++ this would be a no brainer, it's still worth asking.
When creating a getter method for a class that only returns the value of a protected/private member, does the compiler optimize this call so it's the equivalent of referencing that member without having to friend the class and without the overhead of a full method call?
Yes. Both variants compile to the same thing:
struct test
{
int x;
int get() const { return x; }
};
__declspec(noinline) int use_x(const test& t)
{
return t.x;
}
__declspec(noinline) int use_get(const test& t)
{
return t.get();
}
int main()
{
test t = { 111605 };
// pick one:
return use_x(t);
//return use_get(t);
}
Note that it's not as simple as always replacing t.get() with t.x, for the compiler. Consider something like this:
t.get() += 5;
This shouldn't compile, because the result of the function call is an rvalue and += (for primitives) requires an lvalue. The compiler will check for things like that.