How to freeze a variable since it first assigned? - c++

Please assume the version of gcc 7.2.1 in this question
I would like to declare a global variable which behave like a const however, the value to initialize it cannot not be detected before the program being executed. In other words, the target variable would be re-assigned since the first time it is assigned.
An ugly approach of this concept as follow:
#include<iostream>
int numberOfPeople; //Do not re-assign it after it first assign
int main(){
std::cin >> numberOfPeople; // Do not re-assign numberOfPeople since then !!!
// Following of codes omitted.
}
As you could see, this is a very ugly approach and cannot be checked by compiler. I wonder whether there is a kind of notation in c++ that can freeze the variable since it first assigned.
So I can write code like this:
#include<iostream>
magic_notation int numberOfPeople;
int main(){
std::cin >> numberOfPeople; // Allowed as it's first assign.
// Median codes omitted.
numberOfPeople = 60. //Disallowed and will get an error message from compiler!
// Following codes omitted.
}
Is there any kind of notation as can use like the magic_notation in the code above in c++?

The best approach is to make a class with a public const member variable which gets initialized in the constructor:
struct InitInfo {
const int numberOfPeople;
InitInfo() numberOfPeople(getNumberOfPeople()) {
}
private:
static int getNumberOfPeople() {
int res;
cin >> res;
return res;
}
};
InitInfo initInfo;
Now you can use the member variable as follows:
int main() {
cout << initInfo.numberOfPeople << endl;
}
You can use the same approach for initializing a global variable, too.
static int getNumberOfPeople() {
int res;
cin >> res;
return res;
}
const int numberOfPeople = getNumberOfPeople();
int main() {
cout << numberOfPeople << endl;
numberOfPeople += 10; // <<== This triggers an error
}

One approach you can use is to wrap the variable as a static variable in a function. Use the function instead of the variable in rest of your code.
#include <iostream>
int readFromStdin()
{
int n;
cin >> n;
return n;
}
// Wrap it arund in a function.
// int numberOfPeople; //Do not re-assign it after it first assign
int getNumberOfPeople()
{
// Initialize by reading from stdin.
static int numberOfPeople = readFromStdin();
returnn numberOfPeople;
}
int main(){
// Use the function instead of the variable.
getNumberOfPeople();
}

In case you have different ways to initialize the variable, you could come up with something like this:
struct {
int value() const { return _val; }
void init(int val) {
if(!_set) _val = val;
}
private:
int _val;
bool _set = false;
} numberOfPeople;
Now, everybody who uses the variable should call init before using it to make sure it is initialized.

Related

How to pass an input from c++ function to the main function

i want to take an input from c++ function and return it to the main function
, i've already tried to do it but the function returns zero , any idea ?
#include<iostream>
using namespace std;
int input( int x);
int main()
{
int number;
input(number);
cout<<number;
}
int input (int x)
{
cin>>x;
return x;
}
you need to pass by reference
void input (int & x)
{
cin>>x;
}
or use the return value
int main()
{
int number;
number = input();
cout<<number;
}
int input ()
{
cin>>x;
return x;
}
You can change your function to make it take x by reference:
void input (int& x)
{
cin>>x;
}
This way, you don't even need to return x, because your function will update its value as it is passed by reference.
So, let's get it from the begining :
It any function, all its variables are temporary and only accessible in this function's scope unless you use a pointer or a reference(c++ only)
So what happen when you call your function is that a copy of number's is created into x
Also, the return statement of a function is used to... return values! Yeah, weird uh?
So actually you don't even need to send any parameter to your function and just take its result :
#include<iostream>
using namespace std;
int input();
int main()
{
int number = input(); // Takes what the return statement gives
cout<<number;
}
int input ()
{
int x;
cin>>x;
return x;
}
Here's another way by using c++'s references :
#include<iostream>
using namespace std;
void input( int& x);
int main()
{
int number;
input(number);
cout<<number;
}
int input (int& x)//Takes number's address
{
cin>>x;
}

correctly declare pointers, allocate memory, and send them as parameters c++

How correctly declare pointers, allocate memory, and send them as parameters in fuctions to write values ? The code below is what I tried but it doesn't work correctly. I need the same logic. I mean declare, set, then show.
...
struct complex {
int i;
int r;
};
void set(complex *n, int i, int r){
n = new complex;
n->i = i;
n->r = r;
}
void show(complex *n){
std::cout << n->i << " " << n->r;
}
int main(int argc, char* argv[])
{
complex *n;
set(n,10,20);
show(n);
system("pause");
return 0;
}
Actually, your function set couldn't work, because by doing
n = new complex;
whatever the pointer you pass to the function, the pointer will be overwritten by the pointer on the new object.
You can pass the pointer via reference (on C++ only...) like that
void set(complex* &n, int i, int r)
And by doing so you'll modify the value of the original pointer.
You can also simply return the pointer by a return n
But obviously if the prototype of your function must stay like that, it's not possible...
Or, but it's highly discouraged, as many said, you can use a double pointer, and it's quite tricky !
If I don't make mistake, you create a
complex** n
You pass it to your function
set(complex** n, int i, int r)
And then you load
*n = new complex
And it must work if you pass *n to all your function instead of n...
And don't forget to delete your object at the end ;)
Remove the initialization part from set function and put it in the main function.
see this link for explanation.
Why can I not initialize an array by passing a pointer to a function?
Check this code
//#include<windows.h>
#include <iostream>
using namespace std;
struct complex {
int i;
int r;
};
void set(complex *n, int i, int r) {
// n = new complex;
n->i = i;
n->r = r;
}
void show(complex *n) {
std::cout << n->i << " " << n->r;
}
int main(int argc, char *argv[]) {
complex *n = new complex();
set(n, 10, 20);
show(n);
delete n;
//system("pause"); TRY TO AVOID THIS. MAKES YOUR CODE LESS PORTABLE.
return 0;
}
see this link.
c++ - system("pause"); - Why is it wrong? - Stack Overflow

Generalizing compile-time and run-time evaluation

In some occasions, I may need to use the same behavior/code, with values that sometimes are known at run-time and at compile-time. This leads to code repetition:
template<int TValue> struct CompileTime
{
int duplicate() { return TValue * 2; }
};
struct RunTime
{
int value;
RunTime(int mValue) : value{mValue} { }
int duplicate() { return value * 2; }
};
int main()
{
// I need to duplicate a compile-time known value first...
CompileTime<2>{}.duplicate();
// And now I need to duplicate a run-time value...
int value; std::cin >> value;
RunTime{value}.duplicate();
}
Obviously the example is really stupid, but is there any way I can avoid repeating the behavior of duplicate()? (The value needs to be stored, however.)
Ideally, I'd like to write:
int main()
{
// 2 is known at compile-time, calls a "templatized" version of `duplicate`
UnknownTime<2>{}.duplicate();
// `value` is known at run time, calls a "run-time" version of `duplicate`
int value; std::cin >> value;
UnknownTime<value>{}.duplicate();
}
You cannot make templates instantiate at runtime, you can however ditch templates altogether and use c++11 constexpr, which was added to the language exactly for this purpose:
struct AnyTime
{
int value;
constexpr AnyTime(int mValue) : value{mValue} { }
constexpr int duplicate() const { return value * 2; }
};
int main()
{
constexpr int compileTime = AnyTime{2}.duplicate();
int value; std::cin >> value;
int runTime = AnyTime{value}.duplicate();
}
In cases like duplicate you could move to using functions, rather than classes or structures:
template<int TValue>
int duplicate()
{
return TValue * 2;
}
int duplicate(int value)
{
return value * 2;
}
Now you can say:
int main()
{
// 2 is known at compile-time, calls a "templatized" version of `duplicate`
int value1 = duplicate<2>();
// `value` is known at run time, calls a "run-time" version of `duplicate`
int value; std::cin >> value;
int value2 = duplicate(value);
}

No suitable constructor to convert from int to emp

My program simply is to increase the salary int the emp class throw the the function increase
but I'm having this error int the call function line from the line :
No suitable constructor to convert from int to emp
here 's my code :
#include <iostream>
#include <string>
using namespace std;
class emp
{
public:
int salary;
};
void increase(emp x,emp y)
{
x.salary+=100;
y.salary+=250;
}
int main()
{
int value=0;
emp fst, scnd;
cin >> fst.salary >> scnd.salary;
increase(fst.salary,scnd.salary);
cout << fst.salary << endl << scnd.salary << endl;
cin >> value;
return 0;
}
increase expects two emps as parameters, yet you pass in two ints.
Change
increase(fst.salary,scnd.salary);
to
increase(fst,scnd);
Your next question is going to be why the values don't change, so to save you the trouble - it's because you're passing by value, effectively changing copies of your original objects. You'll need to pass by reference:
void increase(emp& x,emp& y)
increase(fst.salary,scnd.salary); should be increase(fst,scnd);, void increase(emp x,emp y) ... should be void increase(emp& x,emp& y) ...
You need to pass emp not int. Further, you are passing parameters by value. Use this instead:
void increase(emp &x,emp &y)
And pass the struct variables; i.e. fst and scnd instead of fst.salary and scnd.salary. Refer this question for better understanding.

Is there some ninja trick to make a variable constant after its declaration?

I know the answer is 99.99% no, but I figured it was worth a try, you never know.
void SomeFunction(int a)
{
// Here some processing happens on a, for example:
a *= 50;
a %= 10;
if(example())
a = 0;
// From this point on I want to make "a" const; I don't want to allow
// any code past this comment to modify it in any way.
}
I can do something somewhat similar with const int b = a;, but it's not really the same and it creates a lot of confusion. A C++0x-only solution is acceptable.
EDIT: another less abstracted example, the one that made me ask this question:
void OpenFile(string path)
{
boost::to_lower(path);
// I want path to be constant now
ifstream ...
}
EDIT: another concrete example: Recapture const-ness on variables in a parallel section.
One solution would be to factor all of the mutation code into a lambda expression. Do all of the mutation in the lambda expression and assign the result out to a const int in the method scope. For example
void SomeFunction(const int p1) {
auto calcA = [&]() {
int a = p1;
a *= 50;
a %= 10;
if(example())
a = 0;
..
return a;
};
const int a = calcA();
...
}
or even
void SomeFunction(const int p1) {
const int a = [&]() {
int a = p1;
a *= 50;
a %= 10;
if(example())
a = 0;
..
return a;
}();
...
}
You could move the code to generate a into another function:
int ComputeA(int a) {
a *= 50;
a %= 10;
if (example())
a = 0;
return a;
}
void SomeFunction(const int a_in) {
const int a = ComputeA(a_in);
// ....
}
Otherwise, there's no nice way to do this at compile time.
A pattern I used to use is to "hide" the argument with an _, so the code becomes
void SomeFunction(int _a)
{
// Here some processing happens on a, for example:
_a *= 50;
_a %= 10;
if(example())
_a = 0;
const int a = _a;
// From this point on I want to make "a" const; I don't want to allow
// any code past this comment to modify it in any way.
}
You could also use only const variables and make a function to compute the new value of a, if necessary. I tend more en more to not "reuse" variables en make as much as possible my variables immutable : if you change the value of something , then give it a new name.
void SomeFunction(const int _a)
{
const int a = preprocess(_a);
....
}
Why not refactor your code in to two separate functions. One that returns a modified a and another that works on this value (without ever changing it).
You could possibly wrap your object too around a holder class object and work with this holder.
template <class T>
struct Constify {
Constify(T val) : v_( val ) {}
const T& get() const { return v_; }
};
void SomeFuncion() {
Constify ci( Compute() ); // Compute returns `a`
// process with ci
}
Your example has an easy fix: Refactoring.
// expect a lowercase path or use a case insensitive comparator for basic_string
void OpenFile(string const& path)
{
// I want path to be constant now
ifstream ...
}
OpenFile( boost::to_lower(path) ); // temporaries can bind to const&
this might be one way to do it, if you are just trying to avoid another name. i suggest you think twice before using this.
int func ()
{
int a;
a %= 10;
const int const_a = a;
#define a const_a
a = 10; // this will cause an error, as needed.
#undef a
}
I don't actually suggest doing this, but you could use creative variable shadowing to simulate something like what you want:
void SomeFunction(int a)
{
// Here some processing happens on a, for example:
a *= 50;
a %= 10;
if(example())
a = 0;
{
const int b = a;
const int a = b; // New a, shadows the outside one.
// Do whatever you want inside these nested braces, "a" is now const.
}
}
Answers were pretty solid, but honestly I can't really think of a GOOD situation to use this in. However in the event you want to Pre-Calculate a constant which is basically what you are doing you have a few main ways You can do this.
First we can do the following. So the compiler will simply set CompileA# for us in this case it's 50, 100, and 150.
const int CompileA1 = EarlyCalc(1);
const int CompileA2 = EarlyCalc(2);
const int CompileA3 = EarlyCalc(3);
int EarlyCalc(int a)
{
a *= 50;
return a;
}
Now anything beyond that there's so many ways you can handle this. I liked the suggestion as someone else had mentioned of doing.
void SomeFunc(int a)
{
const int A = EarlyCalc(a);
//We Can't edit A.
}
But another way could be...
SomeFunc(EarlcCalc(a));
void SomeFunc(const int A)
{
//We can't edit A.
}
Or even..
SomeFunction(int a)
{
a *= 50;
ActualFunction(a);
}
void ActualFunction(const int A)
{
//We can't edit A.
}
Sure, there is no way to do it using the same variable name in C++.