•与函数不同,函数对象可以拥有状态。
这非常有趣,因为std::binary_function、std::less和std::equal_to都有一个const的operator()模板。但是,如果您想要打印具有该对象当前调用计数的调试消息,该怎么做呢?
这是std::equal_to的模板:
struct equal_to : public binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{ return __x == __y; }
};
我能想到3种方法来允许operator()保持const,同时改变成员变量。但哪种方法最好呢?以这个例子为例:
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <cassert>
struct lessThanByTen: public std::less<int>
{
private:
int count;
public:
lessThanByTen() :
count(0)
{
}
bool operator() ( const int& arg1, const int& arg2) const
{
++(*(int*)&count);
++(*(const_cast<int*>(&count)));
{
int incCount = count+1;
const int *iptr = &count;
*(const_cast<int*>(iptr)) = incCount;
}
std::cout << "DEBUG: operator() called " << count << " times.\n";
return (arg1/10) < (arg2/10);
}
};
void test1();
void printArray( const std::string msg, const int nums[], const size_t ASIZE);
int main()
{
test1();
return 0;
}
void test1()
{
int inums[] = {33, 20, 10, 21, 30, 31, 32, 22, };
printArray( "BEFORE SORT", inums, 8 );
std::sort( inums, inums+8, lessThanByTen() );
printArray( "AFTER SORT", inums, 8 );
}
void printArray( const std::string msg, const int nums[], const size_t ASIZE)
{
std::cout << msg << ": ";
for (size_t inx = 0; inx < ASIZE; ++inx)
{
if (inx > 0)
std::cout << ",";
std::cout << nums[inx];
}
std::cout << "\n";
}
因为这3个解决方案都是编译进去的,所以它将计数增加了3。以下是输出结果:
gcc -g -c Main9.cpp
gcc -g Main9.o -o Main9 -lstdc++
./Main9
BEFORE SORT: 33,20,10,21,30,31,32,22
DEBUG: operator() called 3 times.
DEBUG: operator() called 6 times.
DEBUG: operator() called 9 times.
DEBUG: operator() called 12 times.
DEBUG: operator() called 15 times.
DEBUG: operator() called 12 times.
DEBUG: operator() called 15 times.
DEBUG: operator() called 15 times.
DEBUG: operator() called 18 times.
DEBUG: operator() called 18 times.
DEBUG: operator() called 21 times.
DEBUG: operator() called 21 times.
DEBUG: operator() called 24 times.
DEBUG: operator() called 27 times.
DEBUG: operator() called 30 times.
DEBUG: operator() called 33 times.
DEBUG: operator() called 36 times.
AFTER SORT: 10,20,21,22,33,30,31,32
for_each
真的会返回平均值吗?难道不需要使用accumulate
吗?请参见http://www.sgi.com/tech/stl/accumulate.html。在这里,您的第二行将CalculateAvarage()()应用于序列的每个成员,因此您需要一些聪明的运行平均计算,以及一个可以在`for_each`之后查询的CalculateAverage实例。`for_each`将返回您的函数对象的副本。 - juanchopanzastruct Average { double total; uintmax_t count; Average() : total(0), count(0) {} Average operator+(double d) { total += d; count += 1; }; operator double() { return total / count; /* undefined if 0! */ }};
。如果不需要使用二元运算符参数,则无需使用它,而且操作符不需要跟踪计数,累加器可以(也应该)这样做。我认为这与传递给for_each
的函数对象一样清晰,不同之处在于你要实现operator+
而不是operator()
。 - Steve Jessop