It is stated on the site cppreference.com, something like that
For each declarator, the initializer may be one of the following:
( expression-list ) (1)
= expression (2)
{ initializer-list } (3)
comma-separated list of arbitrary expressions and braced-init-lists in parentheses
But in my code
int main(){
int a,b=5,c(a,b);
return 0;
}
when I try to compile, the following error occurs
...error: expression list treated as compound expression in initializer [-fpermissive]
My question is, if list of multiple expressions is allowed in such style of initialization, then why the compiler is not accepting it with variable c?
What am I missing?
All right, let's look at this:
int main(){
int a,b=5,c(a,b);
return 0;
}
What do you expect c(a,b) to actually do?
Let's simplify this just slightly:
int main(){
int a,b=5;
int c(a,b);
return 0;
}
This will generate the same syntax error, but it now stands alone. So...
Your code would work if there were a constructor for int that took two ints as parameters. This would also compile:
int c(int a, int b);
But in that case, you're actually defining a function.
Also, this works:
int main() {
int a = 5;
int b = 10;
int c(b);
std::cout << "C == " << c << std::endl;
}
That works because an int can be initialized from a single int. But you're getting an error because you can't initialize an int from two other ints.
This works:
#include <iostream>
class MyClass {
public:
MyClass(int a, int b): value(a + b) {}
int value;
};
int main() {
int a = 5;
int b = 10;
MyClass c(a, b);
std::cout << "C == " << c.value << std::endl;
}
And maybe that's what the article you read was trying to tell you. Note: cpppreference is NOT a good site for learning C++. Get a good book.
Related
There are quite a few posts on SO with similar titles, but they seem to be triggered by various syntactic errors and I didn't see a consistent pattern yet..
using namespace std;
class A
{
public:
A(int a_) : a(a_) {}
int a;
};
int main()
{
A x{3};
A y{0};
if ((y=x).a)
cout << y.a << endl;
int i = 1;
if (int j = i)
cout << j << endl;
if ((A z = x).a) // error: expected primary-expression before ‘z’
cout << z.a << endl;
(int m = 1); // error: expected primary-expression before ‘int’
}
Am I wrong to assume A z = x is an assignment expression, which should have the same value as z?
Am I wrong to assume A z = x is an assignment expression
Yes, you are wrong. There is no assignment going on here. The = in this statement represents initialization, not assignment. The statement A z = x; defines the variable z, where z is constructed from x. The copy constructor is used here, not copy assignment. It is a declaration statement, not an expression statement.
Your confusion is reasonably common, and it is made worse by the fact that the condition in an if statement can be a declaration of a single non-array variable with a brace-or-equals initializer. Syntactically, a declaration with an "equals" initializer can look a lot like an assignment. A big difference, as you discovered, is that you cannot treat the declaration as a sub-expression. The condition is either a declaration or an expression, not a mix of both.
The good news is that C++-17 added an optional init-statement to the if statement syntax. So what you appear to want would be achieved by the following.
if ( A z = x; z.a ) // Semicolon separates init-statement from condition
cout << z.a << endl;
// At the end of the `if` statement, `z` goes out of scope.
You can't declare a variable in an if statement in that fashion. The declaration has to be of the form:
if (X x = y) ... (or if (auto x = y) ...)
However, you can still achieve what you are trying to do if you provide a suitable conversion operator in class A, like this:
#include <iostream>
using namespace std;
class A
{
public:
A(int a_) : a(a_) {}
int a;
operator bool () { return a != 0; }
};
int main()
{
A x{3};
const A &y = x;
if (y.a)
cout << y.a << endl;
if (A z = x)
cout << z.a << endl;
}
Live demo
#include <iostream>
using namespace std;
void b();
int main() {
int a = 10;
b();
}
void b() {
int a;
cout<<"Int a="<<a;
}
I am looking to print the value of a in the main scope using a function, with my current code, it prints Int a=0. How can I achieve this?
Don't declare an entirely new a inside b().
Pass the a from main to b() and then print that.
For example:
#include <iostream>
void b(int whatever_name_you_want_here);
int main()
{
int a = 10;
b(a);
}
void b(int whatever_name_you_want_here)
{
std::cout << "Int a=" << whatever_name_you_want_here;
}
//Change your code to the following and it will give you the result you're looking for.
On your code there is no way to pass int a on the main to b(); unless b accepts a parameter of the type you want the function to output.
#include<iostream>
void b(int);
int main()
{
int a = 10;
b(a);
}
void b(int a){
std::cout << "int a=" << a;
}
I guess the main problem is not being aware of something very important which is called scope! Scopes are usually opened by { and closed by }
unless you create a global variable, it is only known inside the scope it has been introduced (declared).
you declared the function b in global scope :
void b();
so after this every other function including main is aware of it and can use it.
but you declared the variable a inside the scope of main:
int a = 5;
so only main knows it and can use it.
Please make note that unlike some other programming languages, names are not unique and not every part of the program recognize them in c and c++.
So the part:
void b() {
int a;
does not force the function b to recognize the a which was declared in main function and it is a new a.
so to correct this mistake simply give the value or reference of variable a to function b :
#include <iostream>
void b(int&);
int main() {
int a = 10;
b(a);
}
void b(int& a) {
std::cout << "Int a=" << a << std::endl;
}
please also note that the a as argument of the function b is not the same a in the function main.
The final tip is every argument for functions is known inside that function scope as it was declared inside the function scope!
What you want to achieve requires you to pass a value to a function. Let me give you an example on how to do that.
#include<iostream>
void print_value(int value){
std::cout << "Value is: " << value << '\n';
}
int main(){
int a = 5;
print_value(a);
return 0;
}
The only thing you are missing in your program is the parameter. I won't bother explaining the whole thing over here as there are numerous articles online. Here is a straightforward one.
Refer to this to understand how functions work in C++
Use pass by reference to access a variable which is declared in one function in another.
Refer the below code to understand the use of reference variable,
void swapNums(int &x, int &y) {
int z = x;
x = y;
y = z;
}
int main() {
int firstNum = 10;
int secondNum = 20;
cout << "Before swap: " << "\n";
cout << firstNum << secondNum << "\n";
// Call the function, which will change the values of firstNum and secondNum
swapNums(firstNum, secondNum);
cout << "After swap: " << "\n";
cout << firstNum << secondNum << "\n";
return 0;
}
#include <iostream>
using namespace std;
void displayValue(int number) {
cout<<"Number is = "<<number;
}
int main()
{
int myValue = 77;
displayValue(myValue);
return 0;
}
I'm somewhat new to c++ programming. I couldn't find my answer any where on google so hopefully it can be answered here.
is there a difference between the following
unsigned int counter{ 1 };
or
unsigned int counter = 1;
the book uses the first option and its confusing to me because it doesn't explain the difference. below is the following code from the book i'm following.
#include <iostream>
#include <iomanip>
#include <cstdlib> // contains function prototype for rand()
using namespace std;
int main()
{
for (unsigned int counter{ 1 }; counter <= 20; ++counter) {
cout << setw(10) << (1 + rand() % 6);
// if counter is divisible by 5, start a new line of output
if (counter % 5 == 0) {
cout << endl;
}
}
}
Yes, they are two different types of initialization in C++.
The first one, i.e., unsigned int counter{ 1 }; is a direct initialization.
Whereas, the second one, i.e., unsigned int counter = 1;, is a copy initialization.
For all the details you can directly refer to the documentation.
However, I can emphasize:
Copy-initialization is less permissive than direct-initialization: explicit constructors are not converting constructors and are not considered for copy-initialization.
Initialization references here
For unsigned int type (such in your case), there are no real differences between the two initializations.
Note
The usage of curly braces in the first statement (unsigned int counter{ 1 }) provides an additional constraint:
Otherwise (if T is not a class type), if the braced-init-list has only one element [...], T is direct-initialized [...], except that narrowing conversions are not allowed.
In other words, the usage of curly braces in the initialization does not allow data looseness.
That is:
unsigned int counter{ 12.3 }; // error!!!
won't compile because you are trying to initialize an integer with a floating-point value.
Note this is a "property" of curly braces in the initialization. It is not strictly related to the initialization type.
In fact, you can also write:
unsigned int counter = { 12.3 }; // error!
which is, instead, a copy initialization, but having curly braces does not allows narrowing conversions.
Adding to the other explanations above.
I would use the first option(unsigned int counter{ 1 };) to initialize a list of values for a variable and for a single value, I would prefer to use the second option(unsigned int counter = 1;)
Hope this helps.
Consider the following demonstrative program.
#include <iostream>
struct A
{
int x;
explicit A( int x = 0 ) : x( x ) {}
};
int main()
{
A a1 { 10 };
std::cout << "a1.x = " << a1.x << '\n';
// A a2 = { 10 };
}
In this declaration
A a1 { 10 };
there is used the direct initialization.
And in the commented declaration
// A a2 = { 10 };
that can be also rewritten like
// A a2 = 10;
there is used the copy-initialization. But the constructor declared with the specifier explicit. So the compiler will issue an error. That is it is unable to convert the integer object 10 to the type of A implicitly.
You could write instead
A a2 = A{ 10 };
That is calling the constructor explicitly.
Of course for fundamental types there is no difference because neither constructor is applied except that narrowing conversion is not allowed when the braced initialization is used as for example
int x { 1.0 };
There is a big difference when the type specifier is the placeholder auto.
For example
auto x = 10;
x has the type int.
auto x { 10 };
x again has the type int.
auto x = { 10 };
Now x has the type std::initializer_list<int>.
For example you could rewrite your loop
for (unsigned int counter{ 1 }; counter <= 20; ++counter) {
the following way
for ( auto counter{ 1u }; counter <= 20; ++counter) {
but you may not write
for ( auto counter = { 1u }; counter <= 20; ++counter) {
because in this case the type of the variable counter is std::initializer_list<unsigned int>.
So in general you have the following forms of initializations
T x = value;
T x = { value };
T x( value );
T x { value };
For example
#include <iostream>
int main()
{
int x1 = 1;
std::cout << "x1 = " << x1 << '\n';
int x2 = ( 2 );
std::cout << "x2 = " << x2 << '\n';
int x3( 3 );
std::cout << "x3 = " << x3 << '\n';
int x4{ 4 };
std::cout << "x4 = " << x4 << '\n';
}
The program output is
x1 = 1
x2 = 2
x3 = 3
x4 = 4
But there is one more situation when instead of T() you should use T{} as an initializer. It is when template functions are used.
Consider the following demonstrative program
#include <iostream>
template <class>
void f()
{
std::cout << "f<T>() is called\n";
}
template <int>
void f()
{
std::cout << "f<int>() is called\n";
}
int main()
{
f<int()>();
f<int{}>();
}
Its output is
f<T>() is called
f<int>() is called
The construction int() used as a template argument specifiers the type template argument int while the construction int{} used as a template argument specifiers a non-type template argument of the type int equal to 0.
unsigned int counter = 1 ;
This style of initialization is inherited from C language.
unsigned int counter {1} ;
This style of initialization is of C++.
The difference is if you provide a wrong value while using C++ style initialization
for example:
unsigned int counter {-1} ;
This will give error (use -std=c++11 to compile it)
But this will not give any error.
unsigned int counter = -1 ;
I encountered a situation I don't understand. Would somebody be so nice to explain why first code compiles correctly while second gives an error:
error: the value of 'TestClass::z' is not usable in a constant expression
static constexpr int sum() {return x+y+z;}
----------------------------------------------------^
note: 'int TestClass::z' is not const
static int z;"
Working code:
#include <iostream>
using namespace std;
class TestClass
{
public:
constexpr int sum() {return x+y+z;}
private:
static constexpr int x = 2;
static const int y = 3;
int z = 5;
};
int main()
{
TestClass tc;
cout << tc.sum() << endl;
return 0;
}
But when I try to make TestClass::sum() static I get aforementioned error:
#include <iostream>
using namespace std;
class TestClass
{
public:
static constexpr int sum() {return x+y+z;}
private:
static constexpr int x = 2;
static const int y = 3;
static int z;
};
int TestClass::z = 5;
int main()
{
TestClass tc;
cout << tc.sum() << endl;
return 0;
}
P.S. I'm using mingw32-g++ 4.8.1
In the first case, the result depends only on the function's arguments, including the implicit this used to access z. This doesn't disqualify it from being constexpr - if all the arguments are constant expressions, then so is the result.
In your example, it isn't a constant expression (since tc isn't), but that doesn't matter since it's not being used in a context that requires one. Here's an example showing its use in a constant expression:
constexpr TestClass tc;
array<int, tc.sum()> a;
cout << a.size() << endl;
In the second case, the result also depends on a static variable, whose value could change during the program. This does disqualify it - even if all the arguments are constant expressions, z isn't, and so the result of a function call can never be a constant expression.
I tried asking before but I wasn't very clear so I'm re-asking it.
I want to have a variable that depends on the value of another variable, like b in this example:
int main(){
int a;
dependent int b=a+1; //I'm just making this up
a=3;
cout << b; //prints 4
a=4;
cout << b; //prints 5
}
Of course, this does not exist in C++, but this is what I want.
So instead I tried making a function:
int main(){
int a;
int b(){ return a+1; } //error
a=3;
cout << b(); //would print 4 if C++ allowed nested functions
a=4;
cout << b(); //would print 5 if C++ allowed nested functions
}
The above doesn't work because C++ doesn't allow nested functions.
I can only make functions outside of main(), like this:
int b(){
return a+1; //doesn't work because a is not in scope
}
int main(){
int a;
a=3;
cout << b();
a=4;
cout << b();
}
But this does not work because a is not in the same scope as b(), so I would have to pass a as a parameter and I don't want to do that.
Are there any tricks to get something similar to a dependent variable working in C++?
What you need is a closure. If you can use C++ 0x features, you are in luck. Otherwise, you can define one manually:
#include <iostream>
using namespace std;
struct B
{
const int & a;
B(const int & a) : a(a) {}
// variable syntax (Sean Farell's idea)
operator int () const { return a + 1; }
// function syntax
int operator () () const { return a + 1; }
};
int main()
{
int a;
B b(a);
a = 3;
cout << b << '\n'; // variable syntax
a = 4;
cout << b() << '\n'; // function syntax
}
You can also define B inside main, but some compilers would not like it.
The C++ 0x lambda syntax looks like this:
auto b = [&]() { return a + 1; }
The [&] means that the lambda captures local variables by reference.
If you're using C++0x (GCC 4.5+, Visual C++ 2010), you can use lambdas:
int a = 5;
auto b = [&a]{ return a + 1; };
std::cout << b() << std::endl;
Depending on what you're doing, though, there are probably cleaner solutions - possibly some variation of the classic "method that takes in 'a' and returns 'b'"
You could define a class that had a member a, and then a function b() that returned the value of a+1. A basic implementation would be something like:
class Dependent {
public:
Dependent(void) { m_value = 0; }
void set(int value) { m_value = value; }
int b(void) { return(m_value + 1); }
private:
int m_value;
};
int main(){
Dependent a;
a.set(3);
cout << a.b();
a.set(4);
cout << a.b();
}
You could add operator overloading as appropriate to make it work more like normal integers if you so desired.
This is possible if you use lambda functions (c++0x), because they can capture local variables.
Example:
int main()
{
int a;
auto f = [&] () -> int { return a + 1; };
a = 3;
std::cout << f() << std::endl;
a = 4;
std::cout << f() << std::endl;
return 0;
}
Result:
4
5
(See http://ideone.com/MlzX7 for proof)
A simple approach is to use pre-processor macros, nothing C++ specific about it though:
#define b ((a)+1)
int main(){
int a;
a=3;
cout << b;
a=4;
cout << b;
}
#undef b
Are you OK using C++0x ? if yes,
int main()
{
int a = 10;
auto b = [&a]() -> int { return a + 1; };
cout << b() << endl;
}
Since, it is not tagged with c++0x, you can use nested classes instead of nested functions. This column from Herb sutter would help you for existing c++. http://www.gotw.ca/gotw/058.htm
The above doesn't work because C++ doesn't allow nested functions.
You can simulate that using nested structure. In C++0x you can make use of lambda function, which provides the same means of function inside function.
Define a class called LinkedInt or something that behaves like an int, but has a RelatedTo relationship on itself and an additional member that is a function pointer to the function to evaluate when computing the integer's value. Pretty straightforward. Let me know if you need some pointers on the coding.
The short answer is that OOP is more than enough to bury this problem.
I want to have a variable that depends on the value of another
variable, like b in this example:
I see you just need a reference variable:
int a;
int &b =a;
a=10;
cout << b; // 10
Why C++0x lambdas do come for this, I dont understand.