Scope while initializing static variables - c++

So there is a question I came across
int f() {
return 5;
}
struct A{
static int sX;
static int f() {
return 1;
}
};
int A::sX = f(); // (1)
This complies fine. I wanted to understand why (1) ends up having a
call A::f()
in its compiled code. I understand there is some scope rule being invoked here but would like to know the exact rule. I'd expected it to invoke the global f(). Why doesn't the (unqualified?)name lookup of f yield the global function?
P.S. I'd looked up ADL but since f() doesn't accept any arguments, would ADL kick in?
Edit: I think I found the answer to my question. Check this link under unqualified name lookup which states:
For a name used in the definition of a namespace-member variable
outside the namespace, lookup proceeds the same way as for a name used
inside the namespace:
namespace X {
extern int x; // declaration, not definition
int n = 1; // found 1st
};
int n = 2; // found 2nd.
int X::x = n; // finds X::n, sets X::x to 1

Related

Any way to move constexpr function that returns std::optional inside struct where it is used? [duplicate]

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{};
...
}

Why can I access a struct defined inside a function from outside the function through return type deduction?

I was watching one of Jason Turner's videos and I saw that you can define a type inside a function scope and have it available outside of that scope through function return type deduction.
auto f()
{
struct MyStruct
{
int n;
};
return MyStruct{};
}
int main()
{
auto a = f().n;
return a;
}
Why is this allowed? Is there a paragraph in the C++ 14 standard that allows this?
When trying to get the typeid of MyStruct with clang in compile explorer I saw in the assembly output the type displayed as f()::MyStruct, so there is a scope, but somehow I can access MyStruct outside of that scope. Is this some kind of ADL thing?
No, there's no ADL involved. Since your translation unit contains the definition of the structure, there's no problem in accessing its members.
The important point is that types don't really exist in scopes: names do. And notice that there's no way for you to use the identifier MyStruct instead of auto when declaring a. The name is as inaccessible as it should be. However, as long as you can get at the type without using the inaccessible name, all is fine.
In principle, this is hardly different from using a private member type:
class X
{
struct Hidden
{
int i;
};
public:
Hidden get() const { return {42}; }
};
int main()
{
X x;
auto h = x.get();
assert(h.i == 42);
}

Wrong answer for Upwork C++ Test

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.

Overloaded function name lookup

There are 3 examples:
I.
int foo(int i){ return 0; }
namespace A
{
int foo();
int a = foo(5);//Error: too many argument to function int a::foo()
}
II.
namespace A
{
int foo(int i){ return 0; }
int foo(){ return 1; }
int a = foo(5);//OK, Call A::foo(int)
}
III
namespace A
{
int foo(){ return 1; }
int foo(int i){ return 0; }
int a = foo(5);//OK, Call A::foo(int)
}
What exactly rules used to determine the set of candidate functon? I thought that (3.4.1/1)
name lookup ends as soon as a declaration is found for the name.
It is unclear what declaration (int foo(int) or int foo()) will be found first in the cases II and III?
From §13-1 Overloading,
When two or more different declarations are specified for a single name in the same scope, that name is said
to be overloaded. By extension, two declarations in the same scope that declare the same name but with
different types are called overloaded declarations. Only function and function template declarations can be
overloaded; variable and type declarations cannot be overloaded.
Since you have overloaded function declarations in the same namespace, unqualified name lookup finds matches the set of functions and stops. (I admit the standardese seem a bit incorrect here since it says "as soon as a declaration is found for the name".)
So for II and III, unqualified name lookup finds the same set of overloaded functions.
Extending III a bit further,
int foo(int i) { return 42; }
namespace A {
int foo() { return 1; }
int foo(int i) { return 0; }
int a = foo(5); // OK, Call A::foo(int)
}
Now, it may seem as ::foo(int) and A::foo(int) might be ambiguous but it's not because unqualified name lookup stops after finding A::foo() and A::foo(int). Then it's up to overload resolution to pick the best viable function.
Function overloading only works if the functions are in the same namespace. That is, the name is looked up first by namespace, then by the function signature. In case I, there is a function named foo inside of the A namespace, so it tries to call that, but there is no definition of foo in that namespace which accepts an integer parameter.
In any case, you can call the global foo function as follows:
int a = ::foo(5);
The double colon, with no namespace prefix accesses the global namespace.

Use of variables in global namespace

Why should this be an error?
int a = 0;
a = 42;
int main()
{
}
A possibe match for this behavior i could find:
(3.4.1/4) A name used in global scope, outside of any function, class
or user-declared namespace, shall be declared before its use in global
scope.
Could this be a defect in standard?
int a = 0; //it is a declaration (and definition too) statement
a = 42; //it is an assignment statement
The second line is the cause of error, for it is an assignment statement.
At the namespace-level, only declaration and definition statements are allowed. Assignment-statements are not allowed at namespace level.
And by "shall be declared before its use in global scope" (from the spec's quotation) means the following:
int a = 42;
int b = 2 * a; //a is being used here
int c = a + b; //both a and b are being used here
If you define type instead, then:
struct A {}; //definition of A
struct B { A a; }; //a is declared as member of B
//(which means, A is being "used")
void f(const A&, const B&); //both A and B are used in the declaration of f
You cannot write an assignment statement like that in the global namespace
it needs to be either in main or in some [member] function
int main()
{
a=42;
return 0;
}