如何在C ++中每个值只调用一次函数?

时间:2009-03-13 18:21:28

标签: c++

我正在寻找一个易于使用的宏,只为特定值调用一次函数。例如:

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

6 个答案:

答案 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);}
}