expression

Mar 9, 2023 at 10:41am
I studied in reference book that Any arrangement of variables, constants, and operators that specifies a computation is called an expression. I also studied that Even single variables and constants, like alpha and 37, are considered to be expressions.

 
  cout << "the result is" << number;

In the above statement the variable number is the expression?
Mar 9, 2023 at 10:51am
number is an expression. See:
https://en.cppreference.com/w/cpp/language/expressions

"the result is" is also an expression and perhaps maybe surprising:

cout << "the result is" << number

is also an expression as it returns a type/value (type std::ostream) - not used here.
Last edited on Mar 9, 2023 at 10:58am
Mar 9, 2023 at 11:38am
Basically anything that gives you a value that you can use or print is an expression. Function calls are always expressions even if the return type is void.
Mar 9, 2023 at 12:27pm
> cout << "the result is" << number;

cout - id-expression (primary expression)

"the result is" - literal (primary expression)

cout << "the result is" - subexpression

number - id-expression (primary expression)

cout << "the result is" << number - full-expression (discarded-value expression)

cout << "the result is" << number; - expression statement
Mar 9, 2023 at 1:28pm
JLBorges wrote:
cout << "the result is" - subexpression

A subexpression is essentially an expression that is part of another expression so cout, "the result is" and number are also subexpressions.
Last edited on Mar 9, 2023 at 1:32pm
Mar 10, 2023 at 9:18am
What is the difference between statements and expressions?
Mar 10, 2023 at 9:41am
Mar 10, 2023 at 10:38am
hassan236 wrote:
What is the difference between statements and expressions?

The most important difference is that an expression has a type and will give you a value of that type unless the type is void. A statement does not have a type and does not result in a value.

Examples of expressions:
 
x+9
 
std::gcd(1, 100)
 
foo()


Any expression can be turned into a statement by putting a semicolon after it.

This is an expression:
 
foo()

This is a statement (that contains an expression):
 
foo();


There are also other kind of statements, some of which does not end in a semicolon.

If statements:
1
2
3
4
if (cond)
{
	doSomething();
}

Loop statements:
1
2
3
4
while (x < 100)
{
	std::cout << ++x << "\n";
}

Variable declaration statements:
 
int x = 5;

Note that some of these statements contain other statements and/or expressions.


In some places you are expected to use statements and in other places you are expected to use expressions.

The body of a function contains a list of statements. If you instead write a list of expressions (without semicolons) you would get a compilation error.
1
2
3
4
5
6
void bar()
{
	5+9
	std::gcd(1, 100)    // ERROR! 
	foo()
}

The arguments that you pass to functions should be expressions. You cannot write statements instead. That won't work.
1
2
// This is an error no matter how someFunction is defined:
someFunction(foo();, if(cond){doSomething();});


Last edited on Mar 10, 2023 at 10:41am
Mar 10, 2023 at 11:40am
Statements are fragments of the C++ program that are executed in sequence. An expression statement is an expression followed by a semicolon. See:
https://en.cppreference.com/w/cpp/language/statements
Mar 10, 2023 at 12:10pm
cout is also the expression? how?
Last edited on Mar 10, 2023 at 3:11pm
Mar 10, 2023 at 1:11pm
As in mine and others previous posts,

 
cout << "the result is" << number


is an expression - as cout returns a type and a value.

 
cout << "the result is" << number;


is a statement (with the ;) where the returned value from cout expression is not used. Only the expression side-effects are utilised here (output to the console).
Mar 10, 2023 at 3:58pm
Let's say you using a C++ container like a std::vector, you can overload the insertion operator (<<) so writing an output statement for a container is as simple as outputting a built-in C++ type like an int.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <vector>

// 1D
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
{
   for ( auto const& x : v ) { os << x << ' '; }
   return os;
}

// 2D, which ends up calling the 1D overload as well
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<T>>& v)
{
   for ( auto const& x : v ) { os << x << '\n'; }
   return os;
}

int main()
{
   std::vector vec1D { 1, 2, 3, 4, 5 };

   std::cout << vec1D << "\n\n";

   std::vector<std::vector<int>> vec2D { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };

   std::cout << vec2D << '\n';
}

Returning the std::ostream object in the overload functions chains up the output for proper functioning of the insertion operator.

How the 2 container objects at lines 22 & 26 are instantiated requires C++17 or later, the rest of the code is C++11.

A 3D container will use the 1D and 2D overloads, no need to write an overload for 3D unless it requires different output handling (C++11 or later):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <vector>

template <typename T>
std::ostream& operator<<(std::ostream&, const std::vector<T>&);
template <typename T>
std::ostream& operator<<(std::ostream&, const std::vector<std::vector<T>>&);

int main()
{
   std::cout << "Creating a 3-dimensional vector, enter depth size: ";
   int depth;
   std::cin >> depth;

   std::cout << "Enter row size: ";
   int row;
   std::cin >> row;

   std::cout << "Enter column size: ";
   int col;
   std::cin >> col;

   std::cout << "\n";

   // create a 3 dimensional int vector with known dimensions
   using std::vector;
   vector<vector<vector<int>>> aVector(depth, vector<vector<int>>(row, vector<int>(col, 0)));

   // let's display the initial 3D vector
   std::cout << aVector << '\n';

   // initialize the vector with some values
   for (int depth_loop = 0; depth_loop < depth; depth_loop++)
   {
      for (int row_loop = 0; row_loop < row; row_loop++)
      {
         for (int col_loop = 0; col_loop < col; col_loop++)
         {
            aVector[depth_loop][row_loop][col_loop] = (((depth_loop + 1) * 100)
                                                       + ((row_loop + 1) * 10)
                                                       + col_loop + 1);
         }
      }
   }

   // let's display the filled 3D vector
   std::cout << aVector << '\n';
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
{
   for (auto const& x : v)
   {
      os << x << ' ';
   }

   return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<T>>& v)
{
   for (auto const& x : v)
   {
      os << x << '\n';
   }

   return os;
}

You can overload the extraction operator (>>) as well.

Dealing with a custom class is another use for writing I/O stream overloads.

https://www.geeksforgeeks.org/overloading-stream-insertion-operators-c/
Mar 10, 2023 at 4:44pm
IMO it's easier when dealing with things like vector<vector<... to have using statements for new type defs. Consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <vector>

template <typename T = int>
using Arr1d = std::vector<T>;

template <typename T = int>
using Arr2d = std::vector<Arr1d<T>>;

template <typename T = int>
using Arr3d = std::vector<Arr2d<T>> ;

template <typename T>
std::ostream& operator<<(std::ostream&, const Arr1d<T>&);

template <typename T>
std::ostream& operator<<(std::ostream&, const Arr2d<T>&);

int main() {
	std::cout << "Creating a 3-dimensional vector, enter depth size: ";
	int depth;
	std::cin >> depth;

	std::cout << "Enter row size: ";
	int row;
	std::cin >> row;

	std::cout << "Enter column size: ";
	int col;
	std::cin >> col;

	// create a 3 dimensional int vector with known dimensions
	Arr3d aVector(depth, Arr2d(row, Arr1d(col)));

	// let's display the initial 3D vector
	std::cout << '\n' << aVector;

	// initialize the vector with some values
	for (int rc {}; auto& rw : aVector) {
		rc += 100;
		for (int cc {}; auto& cl : rw) {
			cc += 10;
			for (int ec {}; auto& elem : cl)
				elem = rc + cc + ++ec;
		}
	}

	// let's display the filled 3D vector
	std::cout << aVector;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const Arr1d<T>& v) {
	for (auto const& x : v)
		os << x << ' ';

	return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const Arr2d<T>& v) {
	for (auto const& x : v)
		os << x << '\n';

	return os;
}

Last edited on Mar 13, 2023 at 10:31am
Mar 10, 2023 at 5:52pm
cout is also the expression? how?

In addition to what @seeplus mentions about cout having a type and a value, note that cout is not "built in" to the compiler, it is simply a variable that is defined by the standard library.
Last edited on Mar 10, 2023 at 5:53pm
Topic archived. No new replies allowed.