[英]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.