我正在寻找一个易于使用的宏,只为特定值调用一次函数。例如:
void foo( Object* obj )
{
// Print out the name of each object only once
DO_ONCE( obj, printf("This gets printed only once per object! %s\n",obj->GetName()) );
}
然后
Object obj1("obj1Name"),obj2("obj2Name");
foo(&obj1);
foo(&obj1);
foo(&obj2);
应打印
This gets printed only once per object! obj1Name
This gets printed only once per object! obj2Name
答案 0 :(得分:3)
将您的对象放在容器中并过滤/分组,这样每个对象只出现一次。这可以通过使用set
(或std::tr1::unordered_set
)作为对象的容器来轻松完成。这有效地使它们独一无二。然后,您可以遍历容器。
或者,正如其他人提出的那样,使用函数内部的容器作为记忆设备。但是,总的来说,我认为明确地对结果进行分组可能更合适。
答案 1 :(得分:2)
我更喜欢地图
void foo( Object* obj ){
// Print out the name of each object only once
static std::map<Object*, size_t> calls;
if(calls[obj] == 0) {
std::cout << "This gets printed only once per object! "
<< obj->GetName();
calls[obj] = 1;
}
}
如果您也要计算通话数,也可以决定增加计数器。但请注意,它也不是真正的故障安全。如果你删除一个对象,然后再次新建它并且它碰巧得到相同的地址,那么它将被假定为已经打印过。
答案 2 :(得分:1)
#include <iostream>
#include <ostream>
#include <set>
#include <string>
class Object
{
public:
Object( const std::string& name ):
name_( name )
{}
std::string GetName() const
{
return name_;
}
private:
std::string name_;
};
void print( Object* object )
{
std::cout << object->GetName() << std::endl;
}
template <typename T, typename TFunction>
void doOnce( T* object, TFunction function )
{
static std::set<T*> objectsThatWasThere;
if ( objectsThatWasThere.end() == objectsThatWasThere.find( object ) )
{
function( object );
objectsThatWasThere.insert( object );
}
}
int main()
{
Object obj1("Test");
Object obj2("The");
doOnce( &obj1, print );
doOnce( &obj1, print );
doOnce( &obj1, print );
doOnce( &obj2, print );
doOnce( &obj2, print );
doOnce( &obj2, print );
return 0;
}
答案 3 :(得分:1)
您可能需要记住对象。某事林克
bool do_once( Object * obj )
{
static std::set<Object*> memo;
if ( memo.count(obj) )
{
memo.insert(obj);
return true;
}
return false;
}
#define DO_ONCE(o,a) (do_once(obj) && a)
答案 4 :(得分:1)
#include <set>
...
#define DO_ONCE(type, val, stmt) \
do \
{ \
type __tmp = (val); \
static std::set < type > __memo; \
if (__memo.find(__tmp) == __memo.end()) \
{ \
__memo.insert(__tmp); \
do { stmt; } while(0); \
} \
} \
while(0)
...
DO_ONCE(Object *, obj, printf(...));
答案 5 :(得分:0)
概念:
template<class t1> void do_once(t1* obj) {
static std::map<t1*,bool> was_here;
if (was_here[obj]==false) was_here[obj]=true, throw obj;
}
void ff(int * x)
{
try {do_once(x); } catch (int* obj) { printf("First time: %d\n",*obj);}
}