簡體   English   中英

C ++預處理程序串聯

[英]C++ preprocessor concatenation

我有一個帶有函數指針的函數構建。 我認為嘗試與預處理器宏交換此功能可能會更快。 至少,我想嘗試一下宏,以便可以測量它是否生成更快的代碼。

或多或少是這樣的:

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_to_item->a()不是一個令牌。 假設ptr_to_item是變量名, ptr_to_item 5: ptr_to_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";
}

因為它在那里。

至少有一個弱點。 U不能是模板中的引用類型。 但是由於它已在問題代碼中有效地固定為int ,因此可能根本不需要模板參數U,因此希望它並不過分。

成員指針通常不利於效率。 它們也不利於安全,因為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類的setter / getter-design可能會進一步簡化事情。 無論如何,我建議您嘗試重新設計。 為此,請記住Item實例的職責以及它需要的知識。

干杯,……

–阿爾夫

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM