Why can't I add to a ostringstream outside a method/function - c++

If I use this code outside of a method or winmain:
ostringstream vertexid;
vertexid << "bob";
vertexid << " ";
vertexid << " ";
vertexid << 48348093490;
I get all sorts of syntax errors. How does scope play into this why is this happening?

You can do something like this:
std::ostringstream ss;
#define nil(x) ((x), 0)
int x = nil(ss << "Hello");
int y = nil(ss << ", World!");
int z = nil(ss << std::endl);
If you really don't like thinking up variable names, then you can do something even crazier:
#define nilPASTE(x, y) x ## y
#define nilPASTE2(x, y) nilPASTE(x, y)
#define nil2(x) static int nilPASTE2(line_, __LINE__) = nil(x)
nil2(ss << "Goodbye");
nil2(ss << ", Sun!");
nil2(ss << std::endl);
You asked:
How does scope play into this why is this happening?
I assume you mention scope because that is what some error message spat out. But the answer to both parts of that question is that the C++ compiler is following the rules of the C++ language, which does not allow statements to just appear anywhere. They can only appear where they are allowed, which are in functions and method bodies. The reason my technique is allowed is because I am using expressions, and expressions can appear in more places. In particular, they are allowed to appear in an initializer to a variable. And of course, variable declarations are allowed on the outer most level of a translation unit.
All that gobbly gook means: put your statements inside functions and methods.

You can only declare or define stuff at global scope.
The first line alone would be OK (in an implementation file... if in a header, you risk having multiple definitions and would need to declare it as extern instead of defining it), the next lines are just not legal.

At global namespace you cannot have code, because when should it be executed? You can only put executable statements inside functions, for example WinMain/main.
The execution starts at WinMain/main, then you can call your other functions from there.

Related

Change variable type inside main() C++

I have this code , i need output x variable as double (3.14) without changing anything in the main function
#include <iostream>
int main() {
int x = 3.14;
std::cout << x << "\n";
return 0;
}
What should i do ?
There are two solutions, one correct and one your professor probably wants.
The correct solution (one method, there are other similar ones).
Add this right after the #include line:
int main() {
double x = 3.14;
std::cout << x << "\n";
return 0;
}
#if 0
Add this at the end of the file:
#endif
The incorrect solution for your professor.
Add this line before main:
#define int double
Why is this incorrect? Because #defineing a reserved word is undefined behaviour.
[macro.names] A translation unit shall not #define or #undef names lexically identical to keywords [...]
Why do I think your professor probably wants this? Because I've seen a few C++ assignments, and observed that their authors all too often disregard and abuse the C++ standard.
Your professor might want the first solution instead. I have no way to predict that.

constant, but only for the remainder of this scope

I sometimes encounter cases where it would make sense for a variable to be const, but only for the latter part of its scope. For example, the first part of a block might set the value, and readability of the rest might be improved if it were clear that we were "done" setting that variable -
void foo() {
int n;
// Do things that result in initialization of n
freeze n; // Imaginary construct that declares "n" const for rest of scope
// Later steps that depend on 'n' but do not change it
}
Is there any C++ idiom that captures this pattern? Of course the latter part of the block could be moved to a separate function, but can it be done without moving things around as much?
Your "freeze" code could look like:
const int &refN = n;
and then you use refN instead of n. You could switch the names around.
There are more complicated solutions but you really have to ask yourself whether the gain is worth the pain. If your function is so complicated that you can't see at a glance whether you modified n then you need to refactor your code.
For example, to hide n you could do:
{
const int &_tmp = n;
const int &n = _tmp;
// rest of code
}
but you have to ask yourself if it is worth it. Whoever reads the code after you will wonder what you were smoking.
Another option is for your function to be:
const int n = setup_n();
where you offload the logic to another function, or a lambda:
const int n = [](){
// ...logic...
return finalized_value;
}();
Instead of wrapping the immutable part as lambda, how about wrap the initialization part into lambda and get it as a const int? Then there is no chance to change the mutable int n.
void foo() {
const int n = []() { ;
// Do things that result in initialization of n
return initialized_n;
}();
// Later steps that depend on 'n' but do not change it
}
Using a similar approach as that of #PSkocik's answer (now deleted), you can capture the desired variables in an anonymous lambda and execute the latter. You can even define a variadic macro for this, so you can capture more than one variable using a relatively "clean" syntax:
#include <iostream>
#define WITH_CONST(...) [&, __VA_ARGS__]()
#define DO ();
void foo() {
int n{1}, m{2}, z{3};
WITH_CONST(n, m) // captured variables are immutable in the scope below
{
//++n; // compile-time error
//++m; // compile-time error
++z; // z is mutable, can modify
std::cout << n << " " << m << " " << z << std::endl;
}
DO;
// n and m are not constant anymore
++n;
++m;
std::cout << n << " " << m << " " << z << std::endl;
}
int main()
{
foo();
}
Live on Coliru
It doesn't make the variables constant for all of the remainder of the scope, but it lets you control the scope in which they are constant, and the latter, of course, can be extended to the end of the enclosing scope.

how to access a specific scope in c++?

#include <iostream>
using namespace std;
int x=24 ;
int main()
{
int x=0;
{
int x=5 ;
::x= x+2 ;
}
cout<<::x<<endl ;//first
cout<<x<<endl ; // second
return 0;
}
in this simple example i'm using code block and i know i can modify the global variables using Scope resolution operator.
and i modify the global variable in this example but i wonder if there is a way to modify the variables in specific scope like main function (not necessary the( Scope resolution operator) way )
that mean in this example i need the first output is 24 and the next one 7 .
sorry for my english i hope to understand the question
There are no means to access variables from a specific scope in C++.
If you declare an object or a variable in the inner scope with the same name as an object or a variable in the outer scope, then for all intents and purposes that outer scope's object or variable is not directly visible in the inner scope.
If you already have a pointer or a reference to the outer scope's object, of course, you can still access it indirectly. You just cannot access it directly.
This is a fundamental concept of C and C++; but many other programming languages share the same analogous concept.
The scoping rules of C++ are textual and AFAIK you can't do this, as you can't go putting namespaces inside of functions. But introducing a reference with a unique name may help you as a workaround if you find yourself in a bind like this:
#include <iostream>
using namespace std;
int x = 24;
int main()
{
int x = 0;
int & main_outer_x = x;
{
int x = 5;
main_outer_x = x + 2;
}
cout << ::x << endl; //first
cout << x << endl; // second
return 0;
}
That gives you:
24
7
That shouldn't cost any more memory in your generated code, and lets you keep the outer name untouched. Still, likely to be confusing and error prone if you're purposefully having a name collision within a function. This is abstract code so it's hard to criticize, but most concrete code with such a pattern should probably be done another way.

Replace std::cout with a define

I try to force my compiler to replace any std::cout occurrence in my code with something.
But when I write something like that:
#define std::cout (*some code*)
My compiler spit on my face. Is there a way to do this ?
EDIT :
Here is the code snippet:
# define std::cout (std_out << std::cout)
(std_out is a file I've previously open)
and the error on a line with a std::out occurence
the global scope has no "cout"
You define an identifier, not an arbitrary expression. std is
an identifier; your define will cause the compiler to replace
every instance of the identifier std with ::cout (*some
code*). So it's not surprising that the compiler doesn't like
it: std::cout << toto becomes ::cout (*some code*)::cout <<
toto and std::vector becomes ::cout (*some code*)::vector.
If you'd explain what you're actually trying to achieve, we could probably help you better.
I try to force my compiler to replace any std::cout occurence in my code with something
That's a bad idea. If you are looking for configurable behavior on your output stream, replace all occurrences of std::cout in your code with out, and declare out as std::ostream& out (= whatever stream type you may need).
My compiler spit on my face. Is there a way to do this ?
Not as such. No. You could write:
#define OUTPUT std::cout
OUTPUT << "a = " << a << std::endl;
but you needing a #define to disable (or redirect) your output stream is a sign of bad design (i.e. your define is not the problem you should be trying to solve).
You can make your own version of cout, that actually calls cout, you can place any custom code there:
std::ostream& my_cout() {
/// ...
return std::cout << "a custom message";
}
int main() {
my_cout() << " hi" << std::endl;
}

namespace query

The below code give the compilation error
namespace X{
int i;
}
void f(){
int i;
using X::i; //compile error 'i’ is already declared in this scope
}
But if i replace this line with using namespace X, it compiles fine.
Can someone help understand differences.
Also in the modified code below, I was expecting the output for X::I to be 100 in all places, but it is not.
May be I have misunderstood the namespace concept ?
namespace X{
int i;
}
void f(){
int i=1;
cout << "local I " << i << endl; // prints 1 OK
using namespace X;
i=100;
cout << "X::i " << i << endl; // prints 100 OK.
cout << "X::i " << X::i << endl; // prints 10 why ?
}
main(){
using namespace X;
i=10;
f();
cout << "X::i " << i << endl; //prints 10 why ?
}
Thanks for any help to make me understand this.
In main():
using namespace X;
i = 10;
This sets X::i to 10.
prints 10 why?
That's ^^ why.
Also, in f(): you have another local variable named i that shadows X::i, that's why i resolves to 1 and 100, respectively, and you can only access the other variable in the X namespace by explicitly specifying its namespace.
When you say 'using namespace X'...
if the variable 'i' is defined in X, then, for all references to the variable 'i', the compiler replaces it with 'X::i'. So in main(), when you say i=10, it's setting X::i to 10.
In f()...
you create a NEW variable called i. This is different from X::i. You set i to 1. Then, you begin using namespace X. However, there is a naming conflict--when you say 'i', should it use the local 'i', or X::i? The C++ compiler handles this such case by identifying the variable 'i' with the LOCAL i. Because there is already an i defined in the function, it cannot introduce another i--the i in the namespace. So, in order to reference X::i, you have to explicitly say 'X::i'. Otherwise it thinks you're talking about the LOCAL i.
In the first example, when you say using X::i, you're not giving the compiler much of a choice. You're saying < I WANT TO CALL X::i 'i' >. However, it can't do this--because there's already an 'i' defined. Forcing the compiler to do this would result in two different variables having the same name--which cannot happen.
Hopefully this clarified things a bit. Comment with additional questions.
The using X::i Statement introduces a particular name into the scope. Apparently, the name i was already used so you will not be able to use it again.
Actually, namespaces are used to avoid possible name-clashing. With such short names, namespaces are actually overkill.