简体   繁体   English

C ++预处理程序串联

[英]C++ preprocessor concatenation

I have a function build with function pointers. 我有一个带有函数指针的函数构建。 I think it might be faster to try to exchange this function with pre processor macro. 我认为尝试与预处理器宏交换此功能可能会更快。 At least, I would like to try out the macro so I can measure if it generates faster code. 至少,我想尝试一下宏,以便可以测量它是否生成更快的代码。

It's more or less like this: 或多或少是这样的:

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

And it's called like 就像

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

I think it might be possible to swap this with something like: 我认为可能可以将其与以下内容交换:

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

but it gives me errors like: 但是它给我的错误是:

error: pasting ")" and "setA" does not give a valid preprocessing token 错误:粘贴“)”和“ setA”没有给出有效的预处理令牌

There's a way to concatenate the function names and it's object? 有一种方法可以串联函数名称及其对象?

It is better to use inline functions than macros. 使用内联函数比使用宏更好。 Using any good compiler, this will give you the same efficiency as the macro, but with added type checking and debug symbols if you need them. 使用任何好的编译器,这将为您提供与宏相同的效率,但是如果需要,还可以添加类型检查和调试符号。

Token-pasting means "combining two tokens to form a single token". 令牌粘贴是指“将两个令牌组合成一个令牌”。

You don't want that. 你不要那样 ptr_to_item->a() isn't one token. ptr_to_item->a()不是一个令牌。 Assuming ptr_to_item is a variable name, it's 5: ptr_to_item , -> , a , ( , ) . 假设ptr_to_item是变量名, ptr_to_item 5: ptr_to_item->a()

Your macro should just be: 您的宏应该只是:

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

By the way, for the macro haters, this avoids macros while also avoiding the use of a pointer-to-member-function as a function parameter. 顺便说一下,对于宏恨者,这避免了宏,同时也避免了使用指向成员函数的指针作为函数参数。 It could be tried if the macro is faster than the questioner's function due to the call through a pointer not being inlined. 如果由于没有内联指针的调用而导致宏比提问者的函数快,则可以尝试。 I don't know if/when it will make a difference: 我不知道是否/何时会有所作为:

#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";
}

Because it's there. 因为它在那里。

There's at least one weakness. 至少有一个弱点。 U can't be a reference type in the template. U不能是模板中的引用类型。 But since it's effectively fixed as int in the code in the question, the template parameter U may not be needed at all, so hopefully that isn't too limiting. 但是由于它已在问题代码中有效地固定为int ,因此可能根本不需要模板参数U,因此希望它并不过分。

Member pointers are generally ungood for efficiency. 成员指针通常不利于效率。 They're also ungood for safety, because there's a loophole in the C++ type system regarding accessibility. 它们也不利于安全,因为C ++类型系统在可访问性方面存在漏洞。

Instead of your current design for doStuff like ... 代替您当前的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);

... consider ... ...考虑...

int foo( int value )
{
    // .. Do some stuff 

     return newValue;
}

//...
item.setA( foo( item.a() ) );
item.setB( foo( item.b() ) );
item.setC( foo( item.c() ) );

Getting rid of the setter/getter-design for the Item class will probably simplify things even more. 摆脱Item类的setter / getter-design可能会进一步简化事情。 Anyway, I recommend that you try re-designing. 无论如何,我建议您尝试重新设计。 For that, keep in mind the responsibilites of an Item instance, and what knowledge it needs for that. 为此,请记住Item实例的职责以及它需要的知识。

Cheers & hth., 干杯,……

– Alf –阿尔夫

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM