C++ C++;预处理器串联

C++ C++;预处理器串联,c++,concatenation,c-preprocessor,C++,Concatenation,C Preprocessor,我有一个带有函数指针的函数构建。我认为尝试将此函数与预处理器宏交换可能会更快。至少,我想尝试一下宏,这样我可以测量它是否生成更快的代码 大致是这样的: typedef int (Item::*GetterPtr)(void)const; typedef void (Item::*SetterPtr)(int); void doStuff(Item* item, GetterPtr getter, SetterPtr setter, int k) { int value = (item-

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

大致是这样的:

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”不提供有效的预处理令牌


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

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

标记粘贴意味着“将两个标记组合成一个标记”

你不会想要的
ptr\u to\u item->a()
不是一个令牌。假设
ptr\u to\u item
是一个变量名,它是5:
ptr\u to\u item
->
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";
}
#包括
结构A{
int f;
int foo(){return f;}
void setfoo(inta){f=a;}
};
样板
无效doit(T&obj,英国){
U值=(obj.*GETTER)();
值+=k;
(obj.*设定器)(值);
}
int main(){
A={0};

STD::CUT< P>成员指针通常不利于效率,它们也不利于安全,因为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);
考虑……/P>
int foo( int value )
{
    // .. Do some stuff 

     return newValue;
}

//...
item.setA( foo( item.a() ) );
item.setB( foo( item.b() ) );
item.setC( foo( item.c() ) );
摆脱
类的setter/getter设计可能会使事情更加简化。无论如何,我建议您尝试重新设计。为此,请记住
实例的职责,以及它需要什么知识

干杯


–Alf

+1,我同意。使用这样的宏很讨厌,而且可能不需要。我只想衡量调用成员函数指针的成本,而不仅仅是调用函数。如果函数值得内联,那么生成的程序集中就没有函数调用了。如果不值得内联,那么编译r可能知道它在做什么,而一个宏黑客不会给它带来任何显著的加速。运行时代码的效率与编译时宏相同?我想我必须看到一些证据。这听起来不正确。@Jay:我认为JackN说的是泛泛的。如果函数是内联的,那么为什么它不应该有几乎相同的效率呢与宏一样的性能?事实上,目标代码应该基本相同。当通过指向成员函数的指针调用函数时,
a
setA
是否实际将内联是另一回事,因此这可能是一种相当不寻常的情况。宏与函数不同,因为它删除了潜在的ba优化的目标。@Donotalo而不是doStuff(&item,&item::a,&item::setA,_a);我将其称为dou东西(ptr_to_item,a,setA,_a);如果您只是想测试性能,而无法让一个复杂的宏正常工作,请不要为宏操心。只需写下替换宏后产生的代码即可。很高兴在这里见到您。
:-)
您会喜欢这一个:)