Can someone explain what's going on in this code? (C++)

In summary: N_times compatible class that produces the Fibonacci sequence.class fib {public: fib() : prev(1), value(0) {} std::string... name() { return "Fibonacci sequence"; } int... operator()() { int ret = value; value += prev; prev = ret; return ret; } private
  • #1
Jamin2112
986
12
I was looking at an example from here: http://cboard.cprogramming.com/cplusplus-programming/133294-passing-operator-parameter.html

Code:
template <class T> bool myfunc(bool lv, bool rv, T oper)
{
    return oper(lv, rv);
}
 
struct Or
{
    bool operator()(bool lv, bool rv)
    {
        return lv || rv;
    }
};
 
int main()
{
    bool result = myfunc(true, false, Or());
    return 0;
}

I'm confused about what it means to pass "Or()" into the function. "Or" is a type of struct and he's passing it in what an empty parantheses. Not sure how that has any meaning.
 
Technology news on Phys.org
  • #3
Looks like () is an overloaded operator.
 
  • #5
"In a class definition, the default access for members and base classes is private. In a struct definition, the default is public. That is the only difference between a class and a struct."
 
  • #6
Or() creates an instance of struct Or using the default constructor (not specified, so the freebie provided by the compiler is used). Note also, and this is very important, that struct Or defines a function operator that takes two bools and returns a bool. The function operator is <return_type> operator() (<argument_list>).

Objects such as that instance of struct Or are called function objects, or functors. The C++ standard library makes extensive use of functors. The function operator is a bit funky on first blush, but it is quite powerful. Functors can hold value. Try the following, which should work in both C++03 and C++11:

Code:
#include <iostream>

// Function template for performing some operation <N> times.
// oper must be a functor that defines member functions name() and operator()().
template <int N, typename T>
void apply_N_times (T oper) {
   // Call oper as an object. Functions can't do this. Functors can.
   std::cout << "Applying " << oper.name() << ' ' << N << " times.\n";

   // Call oper as a function N times. Functions can do this, but it's kinda boring.
   // With functors, interesting things can happen because functors can hold state.
   for (int ii = 0; ii < N; ++ii) {
      std::cout << ii << ":" << oper() << "\n";
   }   
}// apply_N_times compatible class that boringly counts.
class count {
public:
   count() : value(0) {}
   std::string name() { return "count"; }
   int operator()() { return value++; }
private:
   int value;
};// apply_N_times compatible class that produces the Fibonacci sequence.
class fib {
public:
   fib() : prev(1), value(0) {}
   std::string name() { return "Fibonacci sequence"; }
   int operator()() {   
      int ret = value;
      value += prev;
      prev = ret;
      return ret;
   }   
private:
   int prev, value;
};int main () {
   apply_N_times<10> (count());
   apply_N_times<10> (fib());
}
 
Last edited:
  • #7
Jamin2112 said:
I know about function pointers (somewhat). I think I was mostly confused by the fact that there was a function defined inside a struct.
Functors are not function pointers. Functors (function objects) are moving toward making functions first class objects in C++. C++11 has gone even further in this regard. It adds std::function, std::bind, and one other little thing: Lambda expressions. Lambda expressions are massively powerful little beasties.
 
  • #8
D H said:
Or() creates an instance of struct Or using the default constructor (not specified, so the freebie provided by the compiler is used). Note also, and this is very important, that struct Or defines a function operator that takes two bools and returns a bool. The function operator is <return_type> operator() (<argument_list>).

Objects such as that instance of struct Or are called function objects, or functors. The C++ standard library makes extensive use of functors. The function operator is a bit funky on first blush, but it is quite powerful. Functors can hold value. Try the following, which should work in both C++03 and C++11:

Code:
#include <iostream>

// Function template for performing some operation <N> times.
// oper must be a functor that defines member functions name() and operator()().
template <int N, typename T>
void apply_N_times (T oper) {
   // Call oper as an object. Functions can't do this. Functors can.
   std::cout << "Applying " << oper.name() << ' ' << N << " times.\n";

   // Call oper as a function N times. Functions can do this, but it's kinda boring.
   // With functors, interesting things can happen because functors can hold state.
   for (int ii = 0; ii < N; ++ii) {
      std::cout << ii << ":" << oper() << "\n";
   }   
}


// apply_N_times compatible class that boringly counts.
class count {
public:
   count() : value(0) {}
   std::string name() { return "count"; }
   int operator()() { return value++; }
private:
   int value;
};


// apply_N_times compatible class that produces the Fibonacci sequence.
class fib {
public:
   fib() : prev(1), value(0) {}
   std::string name() { return "Fibonacci sequence"; }
   int operator()() {   
      int ret = value;
      value += prev;
      prev = ret;
      return ret;
   }   
private:
   int prev, value;
};


int main () {
   apply_N_times<10> (count());
   apply_N_times<10> (fib());
}

In function 'int main()':
Line 42: error: reference to 'count' is ambiguous
compilation terminated due to -Wfatal-errors.
 
  • #9
What compiler are you using? It works fine for me, with gnu and clang, and with c++03 and c++11.
 
  • #10
D H said:
What compiler are you using? It works fine for me, with gnu and clang, and with c++03 and c++11.

I was using this http://codepad.org/ stupid interpreter.
 
  • #11
Codepad has problems. This time the problem is that it apparently is leaking std::count into the global namespace. My code works fine on ideone.com, and also works on codepad if you change count to Count.
 
  • #12
Ok, here's my first time using a functor. You're going to think this is the most pointless program ever. Just for the heck of it, I'm making a library of functions for Group Theory. I could use some suggestions for how to improve my isGroup function.



Code:
#include <set>
#include <iostream>

template <typename ObType, typename BinaryFunction>
bool isGroup(const std::set<ObType> & S, BinaryFunction & op)
{
	/*
	   isGroup returns true or false depending on whether the set S
	   along with the operator op is a group in the Algebraic sense.
	   That is, S is a group if and only if all the 4 following
	   conditions are true: 
			(1) If a, b in S, then a op b in S
			(2) If a, b, c in S, then (a + b) + c = a + (b + c)
			(3) There is an element 0 in S such that a + 0 = 0 + a for all a in S
			(4) If a in S, then there is a b in S such that a + b = b + a = 0
	*/
	typename std::set<ObType>::const_iterator beg(S.cbegin()), offend(S.cend());
	bool noProblemsYet(true), foundIdentity(false);
	ObType iden;
	for (typename std::set<ObType>::const_iterator ia = beg; ia != offend && noProblemsYet; ++ia)
	{
		bool isIdentity = true;
		for (typename std::set<ObType>::const_iterator ib = beg; ib != offend && noProblemsYet; ++ib)
		{
			// ---------- (1) --------------
			if (S.count(op(*ia, *ib)) == 0)
				noProblemsYet = false;
			// ---------- (3) --------------
			if (op(*ia, *ib) != op(*ib, *ia))
				isIdentity = false;
			// -----------------------------
			for (typename std::set<ObType>::const_iterator ic = beg; ic != offend && noProblemsYet; ++ic)
			{
				// ---------- (2) -------------
				if (op(op(*ia, *ib), *ic) != op(*ia, op(*ib, *ic)))
					noProblemsYet = false;
				// ----------------------------
			}
		}
		if (isIdentity)
		{
			foundIdentity = true;
			iden = *ia;
		}
	}
	
	if (noProblemsYet)
	{
		if (!foundIdentity)
			noProblemsYet = false;
		for (typename std::set<ObType>::const_iterator ia = beg; ia != offend && noProblemsYet; ++ia)
		{
			bool foundInverse = false;
			for (typename std::set<ObType>::const_iterator ib = beg; ib != offend && noProblemsYet; ++ib)
			{
				if (op(*ia, *ib) == op(*ib, *ia) && op(*ia, *ib) == iden)
				{
					foundInverse = true;
					break;
				}
			}
			// ---------- (4) -------------
			if (!foundInverse)
				noProblemsYet = false;
			// ----------------------------
		}
	}

	return noProblemsYet;
}

/* ----------------------------- Functors --------------------------------------*/

template <typename T>
class Adder
{
	private:
		static const char symbol = '+';
	public:
		T operator() (const T & x, const T & y) { return x + y; };	
		char getSymbol(void) { return symbol; };
};


template <typename T>
class Subtracter
{
	private:
		static const char symbol = '-';
	public:
		T operator() (const T & x, const T & y) { return x - y; };
		char getSymbol(void) { return symbol; };
};

template <typename T>
class Multiplier
{
	private:
		static const char symbol = '*';
	public:
		T operator() (const T & x, const T & y) { return x * y; };
		char getSymbol(void) { return symbol; };
};

template <typename T>
class Divider
{
	private:
		static const char symbol = '/';
	public:
		T operator() (const T & x, const T & y) { return x / y; };
		char getSymbol(void) { return symbol; };
};

template <typename T>
class Modder
{
	private:
		static const char symbol = '%';
	public:
		T operator() (const T & x, const T & y) { return x % y; };
		char getSymbol(void) { return symbol; };
};

/* ------------------------------------------------------------------------------*/


int main()
{
	std::set<int> S1 = { 0, 1, -1 };
	std::set<int> S2 = { 0 };
	class Adder<int> p;
	std::cout << isGroup(S1, p);
	return 0;
}
 
  • #13
Your test for an identity element is wrong. Your code if (op(*ia, *ib) != op(*ib, *ia)) { isIdentity = false; } clears isIdentity when the group operation is non-commutative. You should be checking whether op(*ia, *ib) != *ib.
 
  • #14
D H said:
Your test for an identity element is wrong. Your code if (op(*ia, *ib) != op(*ib, *ia)) { isIdentity = false; } clears isIdentity when the group operation is non-commutative. You should be checking whether op(*ia, *ib) != *ib.

Actually, shouldn't I be looking at

Code:
(op(*ia, *ib) != op(*ib, *ia) || op(*ib, *ia) != *ib)

?

Wikipedia's page (http://en.wikipedia.org/wiki/Group_(mathematics )) says the identity element must satisfy 0 + a = a + 0 = a.
 
Last edited by a moderator:

1. What is the purpose of this code?

The purpose of this code is to perform a specific task, which could vary depending on the program. It is written in the C++ programming language, which is commonly used for developing software applications.

2. How does this code work?

This code works by following a series of instructions, written in a specific syntax, to complete a task. It may involve manipulating data, performing calculations, or interacting with other components of a larger program.

3. What do the different parts of the code mean?

The different parts of the code, such as variables, functions, and operators, each have a specific purpose and can be combined to create a program. For example, variables store data, functions perform operations, and operators manipulate values.

4. Can someone explain the logic behind this code?

The logic behind this code refers to the reasoning and thought process used to design and implement the program. It involves breaking down the task into smaller, manageable steps and determining the most efficient way to achieve the desired outcome.

5. How can I modify this code to fit my specific needs?

The code can be modified by making changes to the instructions, such as adding, removing, or modifying lines of code. It is important to have a thorough understanding of the code and its purpose before making any modifications to ensure the program still functions correctly.

Similar threads

  • Programming and Computer Science
Replies
1
Views
1K
  • Programming and Computer Science
Replies
1
Views
1K
  • Programming and Computer Science
Replies
3
Views
1K
  • Programming and Computer Science
Replies
3
Views
1K
  • Programming and Computer Science
2
Replies
55
Views
11K
  • Programming and Computer Science
Replies
7
Views
11K
  • Programming and Computer Science
2
Replies
53
Views
3K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
1K
  • Programming and Computer Science
Replies
2
Views
6K
  • Engineering and Comp Sci Homework Help
Replies
1
Views
859
Back
Top