Boolean Expression does not Work

Why didn't my lambda expression filter out the 8.8 from the output?

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
//	C21Drill Test.cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <numeric>
#include <iterator>

int main()
{
	//	Read some floating point values (at least 16 values)
	//	from a file into a a vector<double> called vd.
	std::ifstream ist{ "v2.txt" };
	std::vector<double> vd;
	if (!ist) std::cerr << "can't open input file!" << '\n';
	for (double fp; ist >> fp;)
		vd.push_back(fp);

	//	Compute the mean value of the elements in vd; output it
	double total = std::accumulate(vd.begin(), vd.end(), 0);
	double mean = total / vd.size();
	std::cout << "mean == " << mean << '\n';

	//	Make a new vector<double> called vd2 and copy all
	//	elements of vd with values lower than (less than) the mean into vd2.
	std::vector<double> vd2(vd.size());
	auto it = std::copy_if(vd.begin(), vd.end(), vd2.begin(), [mean](int x) {return x < mean; });
	
	vd2.resize(std::distance(vd2.begin(), it));
	for (const auto mm : vd2)
		std::cout << "mm == " << mm << '\n';
}


Here is the contents of v2.txt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1.1
16.16
2.2
15.15
3.3
14.14
4.4
13.13
9.9
12.12
8.8
11.11
6.6
10.10
5.5
9.9


Here is my output:

mean == 8.625
mm == 1.1
mm == 2.2
mm == 3.3
mm == 4.4
mm == 8.8
mm == 6.6
mm == 5.5
Press any key to continue . . .
Last edited on
Line 27, in lambda, int should be double
Thank you codewalker for finding my error.

I now changed the lambda expression to a Boolean expression, it does not work. Here's the code:
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
//	C21Drill Test.cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <numeric>
#include <iterator>


int main()
{
	//	Read some floating point values (at least 16 values)
	//	from a file into a a vector<double> called vd.
	std::ifstream ist{ "v2.txt" };
	std::vector<double> vd;
	if (!ist) std::cerr << "can't open input file!" << '\n';
	for (double fp; ist >> fp;)
		vd.push_back(fp);

	//	Compute the mean value of the elements in vd; output it
	double total = std::accumulate(vd.begin(), vd.end(), 0);
	double mean = total / vd.size();
	std::cout << "mean == " << mean << '\n';

	//	Make a new vector<double> called vd2 and copy all
	//	elements of vd with values lower than (less than) the mean into vd2.
	std::vector<double> vd2(vd.size());
	bool less_than_mean(double x) { return x < mean; }; //error

	auto it = std::copy_if(vd.begin(), vd.end(), vd2.begin(), less_than_mean);
	
	vd2.resize(std::distance(vd2.begin(), it));
	for (const auto mm : vd2)
		std::cout << "mm == " << mm << '\n';
}


There is a red squiggly line under the brace that indicates "Error: expect a ';'
why is there a function definition inside a function?
bool less_than_mean(double x) { return x < mean; };
this isnt legal in c++, you should define it outside. it will fix your error
I put it inside of main because "mean" is not yet defined on the outside. I inserted it inside of main after "mean" was defined.

Sure enough, when I put the function outside of main, I get error: identifier "mean" is undefined.
I found the solution. I made a function object and it worked. Here is the code:
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
//	C21Drill Test.cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <numeric>
#include <iterator>

class less_than_mean {
	double mean;
public:
	less_than_mean(double xx) : mean(xx) {}
	bool operator()(double xx) const { return xx < mean; };

};

int main()
{
	//	Read some floating point values (at least 16 values)
	//	from a file into a a vector<double> called vd.
	std::ifstream ist{ "v2.txt" };
	std::vector<double> vd;
	if (!ist) std::cerr << "can't open input file!" << '\n';
	for (double fp; ist >> fp;)
		vd.push_back(fp);

	//	Compute the mean value of the elements in vd; output it
	double total = std::accumulate(vd.begin(), vd.end(), 0);
	double mean = total / vd.size();
	std::cout << "mean == " << mean << '\n';

	//	Make a new vector<double> called vd2 and copy all
	//	elements of vd with values lower than (less than) the mean into vd2.
	std::vector<double> vd2(vd.size());


	auto it = std::copy_if(vd.begin(), vd.end(), vd2.begin(), less_than_mean(mean));
	
	vd2.resize(std::distance(vd2.begin(), it));
	for (const auto mm : vd2)
		std::cout << "mm == " << mm << '\n';
}


By the way, although I get the error: identifier "mean" is undefined when I put the Boolean expression outside of main, the code compiled to my surprise. Usually, when there is a red squiggly line, the code does not compile.
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
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <iterator>
#include <functional>

int main()
{
    const std::vector<double> vd { 1.1, 16.16, 2.2, 15.15, 3.3, 14.14, 4.4, 13.13,
                                   9.9, 12.12, 8.8, 11.11, 6.6, 10.10, 5.5, 9.9 } ;

    //    Compute the mean value of the elements in vd; output it
    // double total = std::accumulate( vd.begin(), vd.end(), 0 ); // **** type of literal 0 is int
    const double total = std::accumulate( vd.begin(), vd.end(), 0.0 );
    const double mean = total / vd.size();
    std::cout << "mean == " << mean << '\n';

    //	Make a new vector<double> called vd2 and copy all
    //	elements of vd with values lower than (less than) the mean into vd2.

    // std::vector<double> vd2(vd.size());
    std::vector<double> vd2 ;

    // the result of evaluating a lambda expression is a callable object
    // auto v - polymorphic lambda expression: type of v is deduced when called (C++14)
    const auto less_than_mean = [mean] ( auto v ) { return v < mean ; } ;

    // http://en.cppreference.com/w/cpp/iterator/back_inserter
    std::copy_if( vd.begin(), vd.end(), std::back_inserter(vd2), less_than_mean );
    for( const auto mm : vd2 ) std::cout << mm << ' ';
    std::cout << '\n' ;

    vd2.clear() ;

    // the result of evaluating a bind expression is a callable object
    // std::greater<>::operator() - polymorphic, deduces argument and return types (C++14)
    // http://en.cppreference.com/w/cpp/utility/functional/greater_void
    using std::placeholders::_1 ;
    const auto greater_than_mean = std::bind( std::greater<>(), _1, mean ) ;

    std::copy_if( vd.begin(), vd.end(), std::back_inserter(vd2), greater_than_mean );
    for( const auto mm : vd2 ) std::cout << mm << ' ';
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/edbc93d83555a361
JLBorges,

Thank you very much for all the information.

1. The use of const in lines 15 and 16 for the variables "total" and "mean" make them immutable. Are there other advantages in the use of const?

2. What are the differences between back_inserter and push_back? Why did you use back_inserter instead of push_back when both add elements to the end of the vector and push_back is a member function of vector<>?

> The use of const in lines 15 and 16 for the variables "total" and "mean" make them immutable.
> Are there other advantages in the use of const?

In this case, there is really no practical advantage in using const.
I tend to use const profusely. I've discovered (the hard way) that it is a good programming habit to acquire.


> What are the differences between back_inserter and push_back?

back_inserter(c) yields an output iterator; std::back_insert_iterator<>.
This iterator can be used to add elements to the back of the container.

push_back is an operation on the container.


> Why did you use back_inserter instead of push_back?

std::copy_if() is an algorithm that selectively copies elements in one range to another range; it requires an iterator that 'points' to the beginning of the destination range.

These two are equivalent:
1
2
std::copy_if( vd.begin(), vd.end(), std::back_inserter(vd2), less_than_mean ) ;
for( const auto& value : vd ) if( less_than_mean(value) ) vd2.push_back(value) ;
Thank you for the explanations, JLBorges.
Topic archived. No new replies allowed.