namespace myspace { int x } Now why `myspace::x=3;` gives error? - c++

Code
#include <iostream>
namespace myspace
{
int x;
}
myspace::x=3; // This line is giving error.
int main()
{
myspace::x=5;
return 0;
}
Output
Error: C++ requires a type specifier for all declarations
So why line myspace::x=3; giving error that C++ requires a type specifier for all declarations ?

The statement
myspace::x=3;
isn't an initialization, it's a plain assignment. It's no different from the
myspace::x=5;
you have inside the main function.
Any statement that isn't a declaration or a definition can't be outside functions.
If you want to initialize the variable, do it at the definition:
namespace myspace
{
int x = 3;
}

You provided a definition upon first declaring the variable. And as others noted myspace::x=3; constitutes an assignment expression at namespace scope, which is not allowed.
If you want to declare the variable without defining it, you need to be explicit and specify it's an extern declaration.
namespace myspace
{
extern int x;
}
The definition would still need the type specifier (as all definitions do), but it will look somewhat like what you imagined
int myspace::x = 3;
While all of this is fine and dandy, global variables (the mutable, run-time external kind) are a code smell. So best not to get in the habit of using them.

Related

Why can't the using keyword be used for a forward declaration when defining a function?

Given the following header and source, in which a simple function GiveMeATwo is forward declared in the header test.hpp, within the namespace SomeNamespace, why does a conflict occur when trying to bring the function GiveMeATwo into scope via using SomeNamespace::GiveMeATwo, prior to defining GiveMeATwo?
test.hpp
#ifndef _TEST_HEADER_
#define _TEST_HEADER_
namespace SomeNamespace {
int GiveMeATwo();
}
#endif
test.cpp
#include "test.hpp"
using SomeNamespace::GiveMeATwo;
int GiveMeATwo() {
return 2;
}
Compiling with Apple clang version 14.0.0 (clang-1400.0.29.202) yields the following error, indicating that the using statement somehow implicitly introduces a declaration?
test.cpp:5:5: error: declaration conflicts with target of using declaration already in scope
int GiveMeATwo() {
^
./test.hpp:6:5: note: target of using declaration
int GiveMeATwo();
^
test.cpp:3:22: note: using declaration
using SomeNamespace::GiveMeATwo;
^
1 error generated.
Furthermore, what is the difference between bringing the GiveMeATwo symbol into scope via using namespace SomeNamespace, versus using SomeNamespace::GiveMeATwo as I have done here?
To quote cppreference:
If an entity is declared, but not defined in some inner namespace, and then declared through using-declaration in the outer namespace, and then a definition appears in the outer namespace with the same unqualified name, that definition is a member of the outer namespace and conflicts with the using-declaration
In other words, this definition:
int GiveMeATwo() {
return 2;
}
is for another function. If you want to define the one in SomeNamespace, you still need to name the namespace, even if you wrote using SomeNamespace::GiveMeATwo; or using namespace SomeNamespace; before it:
int SomeNamespace::GiveMeATwo() {
return 2;
}
Demo
The using-directive (using namespace) is slightly different because:
Using-directive does not add any names to the declarative region in which it appears (unlike the using-declaration), and thus does not prevent identical names from being declared.
So you can do this:
namespace SomeNamespace {
int GiveMeATwo();
}
using namespace SomeNamespace;
int GiveMeATwo() {
return 2;
}
but it's somewhat useless because a call to GiveMeATwo is now ambiguous unless you qualify it, like ::GiveMeATwo(); for the outer function or SomeNamespace::GiveMeATwo(); for the inner one.

can I have operations outside a function body in c++?

#include <stdio.h>
#include <iostream>
using namespace std;
int val = 100;
//cout<<val<<endl; //this is not valid.
int main(){
int val=100; //why this is valid?
return 0;
}
I found out these two things in the above code:
cout<<val<<endl; is not valid outside the main function body. Why is that?
I think the two vals are all defined in the namespace std. But how come they are both valid?
cout<<val<<endl; is not valid outside the main function body. Why is that?
Because the standard says that expression statements can only be in block scope.
can I have operations outside a function body in c++?
You can't have expression statements outside a function.
However, declaration statements can have sub-expressions that have side-effects such as cout<<val<<endl (note the lack of semicolon) in which case those expressions will be executed during initialisation of whatever was declared. Neil Butterworth shows an example of this in their answer.
I think the two vals are all defined in the namespace std
You think wrong. Neither is declared in the std namespace.
One val is declared in the global namespace, while the other is declared in the function scope. Declaring one variable in a nested scope within potential scope of another vairable with the same name is called shadowing i.e. val in the block scope shadows val in the namespace scope.
void main()
This is also not valid. main must return int.
You can initialise things, possibly via function calls, so you could say something like:
ostream & os = cout<< 42 <<endl;
but the utility of this is not obvious, and you would possibly run into problems with the order of instantiation of objects like cout.
What you cannot do is write code such as:
x = x + 1;
for ( int y = 0; y < 10; y++ ) {}
outside of a function - that's the way the language is defined.
And in your code neither val is in the std namespace, and it would be illegal to try to place them there. You need to read up on scope.

A using-declaration can not be repeated in function scope. Why is that?

In [namespace.udecl]/10 you have the following example:
namespace A {
int i;
}
namespace A1 {
using A::i;
using A::i; // OK: double declaration
}
void f() {
using A::i;
using A::i; // error: double declaration
}
This snippet compiles in clang.
The first is a declaration inside a namespace, and the multiple using statements could happen frequently using #includes. The second is inside a definition of a function, and you would never do that unless you made a mistake. You can't define the same symbol twice either, for example, but you can declare several times.
The using statement is also more than just a declaration. It is a bit stronger, as it imports a function from one namespace to another. For example, it can pull a protected base class member function into a derived class, making it public. It's almost a definition by linkage.

An extern variable located in a function?

According to wikipedia:
http://en.wikipedia.org/wiki/External_variable
An external variable may also be declared inside a function.
What is the purpose of an extern variable being declared within a function? Would it have to be static too?
It allows for restricting access to a global to some scope:
int main()
{
extern int x;
x = 42; //OKAY
}
void foo()
{
x = 42; //ERROR
}
int x;
The external declaration goes inside a function. It simply means that no other functions can see the variable.
void func()
{
extern int foo;
foo ++;
}
void func2()
{
foo--; // ERROR: undeclared variable.
}
In another source file:
int foo; // Global variable. Used in the other source file,
// but only in `func`.
It is just a way to "isolate" a variable, so it doesn't accidentally get used in places where it isn't supposed to be used.
The only difference between declaring an external variable at namespace scope:
extern int x;
void foo() {
cout << x;
}
and declaring it at function scope:
void foo() {
extern int x;
cout << x;
}
is that in the latter case, x is only visible inside the function.
All you're doing is further tightening the scope of the extern declaration.
Here's an analogous example using namespaces:
At namespace scope:
#include <string>
using std::string;
void foo() {
string str1;
}
string str2; // OK
At function scope:
#include <string>
void foo() {
using std::string;
string str1;
}
string str2; // Error - `using` not performed at this scope
The extern keyword says that an identifier has external linkage. This means that it is linked to the same name anywhere else it is declared with external linkage. That is, the different instances of the name in different places refer to the same object.
Declaring an identifier inside a block (including the block that defines a function) gives it block scope. The scope of that instance of the identifier ends at the end of the block.
Combining extern with block scope allows a function to see an external identifier without cluttering the name space of other functions. (Nonetheless, it is often bad practice.)
The text refers to a non-defining declaration of an extern variable inside function. Extern definitions inside functions are illegal.
So, a non-defining declaration of an extern variable inside function simply means that you want to use that variable inside that function. The variable itself must be a global variable defined elsewhere.
Basically, if you don't need access to that global variable (defined elsewhere) in the entire translation unit and just need it inside that function, it is perfectly good idea to declare it locally. That way you are not polluting global namespace with identifiers no other function needs.

Why can't I assign a value to a variable in a namespace?

My code is like below, when I compile it , I receive this error :
two.cpp:5: error: expected constructor, destructor, or type conversion before '=
' token
#include <iostream>
using namespace std;
namespace a1{
int a=3;
a=4;
}
int main(){
cout << a1::a<<endl;
}
I encountered this problem when I defined a namespace in two files, in the second file, I can't assign a value to a variable which defined in the first file.
I am learning Beginning ANSI C++ , and can't find any information about this in the book.
The purpose of namespaces is to avoid conflicting names. So surround your variable and class declarations with namespaces. But namespaces by themselves don't provide the scaffolding for running code. What is going on with your a=4; statement ? Where is that supposed to execute ? You need to put it in a function or method, not in a namespace.
You can have declarations (which include that you can have definitions) at namespace scope, e.g.
int a = 3;
But you can not have non-declaration statements at namespace scope.
For example, an assignment such as
a = 4;
is not a declaration: it purely asks for an effect.
However, you can put that in the body of a function, e.g. in main.
Cheers & hth.,
Does your second file knows about the definition of int a; ? Namespaces don't magically work like in some other languages, you still have to include a header file containing the definition of your int a at the other file, or at list define it as external.