代码之家  ›  专栏  ›  技术社区  ›  Vitor Py

C++预处理器级联

  •  0
  • Vitor Py  · 技术社区  · 15 年前

    我有一个带有函数指针的函数构建。我认为尝试用预处理器宏交换此函数可能更快。至少,我想试试宏,这样我就可以测量它是否生成更快的代码。

    差不多是这样的:

    typedef int (Item::*GetterPtr)(void)const;
    typedef void (Item::*SetterPtr)(int);
    
    void doStuff(Item* item, GetterPtr getter, SetterPtr setter, int k)
    {
        int value = (item->*getter)();
    
        // .. Do some stuff 
    
        (item->*setter)(newValue);
    }
    

    它被称为

    // ...
    doStuff(&item, &Item::a, &Item::setA, _a);
    doStuff(&item, &Item::b, &Item::setB, _b);
    doStuff(&item, &Item::c, &Item::setC, _c);
    // ...
    

    我认为可以用如下方式交换:

    #define DO_STUFF(item, getter, setter, k) do { \
    int value = item ## -> ## getter ## (); \
    //... \
    item ## -> ## setter ## (newValue); \
    } while(0);
    

    但它给了我错误,比如:

    错误:粘贴”)“和”seta“未提供有效的预处理标记

    有一种方法可以连接函数名和它的对象?

    3 回复  |  直到 9 年前
        1
  •  3
  •   Steve Jessop    15 年前

    令牌粘贴是指“将两个令牌组合成一个令牌”。

    你不想那样。 ptr_to_item->a() 不是一个代币。假设 ptr_to_item 是一个变量名,它是5: PtRyToTi项 , -> , a , ( , ) .

    您的宏应该是:

    #define DO_STUFF(item, getter, setter, k) do { \
        int value = (item)->getter(); \
        //... \
        (item)->setter(newValue); \
    } while(0);
    

    顺便说一下,对于讨厌宏的人来说,这避免了宏,同时也避免了使用指向成员函数的指针作为函数参数。如果由于通过指针的调用没有内联,宏的速度比查询者的函数快,则可以尝试使用该方法。我不知道它是否/何时会有影响:

    #include <iostream>
    
    struct A {
        int f;
        int foo() {return f;}
        void setfoo(int a) { f = a; }
    };
    
    template <typename T, typename U, U (T::*GETTER)(), void (T::*SETTER)(U)>
    void doit(T &obj, U k) {
        U value = (obj.*GETTER)();
        value += k;
        (obj.*SETTER)(value);
    }
    
    int main() {
        A a = {0};
        std::cout << a.foo() << "\n";
        doit<A,int,&A::foo, &A::setfoo>(a,1);
        std::cout << a.foo() << "\n";
        doit<A,int,&A::foo, &A::setfoo>(a,2);
        std::cout << a.foo() << "\n";
    }
    

    因为它就在那里。

    至少有一个弱点。u不能是模板中的引用类型。但是因为它实际上被固定为 int 在所讨论的代码中,模板参数u可能根本不需要,所以希望这不太受限制。

        2
  •  5
  •   jacknad    15 年前

    使用内联函数比使用宏要好。使用任何好的编译器,这将给您提供与宏相同的效率,但如果需要,还可以添加类型检查和调试符号。

        3
  •  2
  •   Cheers and hth. - Alf    15 年前

    成员指针通常不适合提高效率。它们也不利于安全,因为C++类型的系统在可访问性方面存在漏洞。

    而不是你目前的设计 doStuff 像…

    typedef int (Item::*GetterPtr)(void)const;
    typedef void (Item::*SetterPtr)(int);
    
    void doStuff(Item* item, GetterPtr getter, SetterPtr setter, int k)
    {
        int value = (item->*getter)();
    
        // .. Do some stuff 
    
        (item->*setter)(newValue);
    }
    
    //...
    doStuff(&item, &Item::a, &Item::setA, _a);
    doStuff(&item, &Item::b, &Item::setB, _b);
    doStuff(&item, &Item::c, &Item::setC, _c);
    

    …考虑…

    int foo( int value )
    {
        // .. Do some stuff 
    
         return newValue;
    }
    
    //...
    item.setA( foo( item.a() ) );
    item.setB( foo( item.b() ) );
    item.setC( foo( item.c() ) );
    

    摆脱了 Item 类可能会更简化一些事情。无论如何,我建议你尝试重新设计。为此,请记住 项目 例如,它需要什么样的知识。

    干杯!

    阿尔夫