2011-06-29 58 views
2

我想要做的東西像下面這樣:局部變量作爲非類型模板參數

Example(&Class::MemberFunction, this)); 

//... 

template<class T_CLASS> 
inline static void Example(void (T_CLASS::*MemberFunctionPointer)(), T_CLASS* InstancePointer) 
{ 
    SomeClass<T_CLASS>::Bind<MemberFunctionPointer>(InstancePointer); 
} 

但我得到的錯誤:*模板參數「T_MEMBER_FUNCTION」:「MemberFunctionPointer」:一個局部變量不能使用作爲非類型參數*

針對此問題的任何解決方案?我想提供一個更簡單的方法來調用「綁定」

謝謝了Mirco

//編輯:

我想MemberFunctionPointer是一個非類型模板參數,因爲在「綁定」我需要再次它作爲模板參數。 正如你在答案中寫的,在我的情況下,MemberFunctionPointer是一個變量,它的值在編譯時是未知的。但MemberFunctionPointer總是指向相同的函數。有沒有一種方法可以讓它保持不變,以便編譯器在編譯時知道它?

+0

請看看這個非常類似的問題http://stackoverflow.com/q/6041570 – sharptooth

回答

0

MemberFunctionPointer是一個變量不是型(或編譯時間常數),因此無法使用,你需要的是一個函數的真正簽名,這樣的事情可能會更好..

template<typename T_FUNC_PTR, class T_CLASS> 
inline static void Example(T_FUNC_PTR fPtr, T_CLASS* InstancePointer) 
{ 
    SomeClass<T_CLASS>::Bind<T_FUNC_PTR>(fPtr, InstancePointer); 
} 

即讓編譯器推斷出函數指針的類型(注:你將不得不指針傳播到功能太),調用

Example(&foo::bar, foo_inst); 

這是未經測試,把我的頭頂部,所以語法可能是稍微偏離...

編輯:這裏是一個簡單的例子來說明這一概念:

#include <iostream> 
struct foo 
{ 
    void bar() { std::cout << "foo::bar()" << std::endl; } 
}; 

template<typename T_FUNC_PTR, typename T_CLASS> 
void exec(T_FUNC_PTR ptr, T_CLASS& inst) 
{ 
    (inst.*ptr)(); 
} 

int main(void) 
{ 
    foo inst; 
    exec(&foo::bar, inst); 
} 
+0

你的第一句話建議只有類型可以用作模板參數。這不是真的。 C++的模板系統也接受非類型參數。但是這些必須是*編譯時*常量的整型或指針/引用某些外部鏈接。 – sellibitze

+0

@sellibitze,真的嗎?我明確指出,變量是一個變量,而不是一個類型...我想我會更加明確...... – Nim

+0

感謝您的回覆。正如我上面所描述的,我希望我的成員函數指針是一個非類型的模板參數。當在我的「綁定」調用中像傳遞一樣時,沒有任何問題 - 但我希望有一個更容易使用的包裝函數「示例」,它不包含模板參數。示例應獲取MemberFunctionPointer作爲參數,並將其作爲非類型模板參數傳遞給「綁定」。它總是指向相同的函數,我想讓編譯器在編譯時知道它。這可能嗎? – Mirco

4

有兩種東西的模板參數可以是:類型和編譯時間常數表達式 。函數參數的內容不是編譯時可確定的值。因此,編譯器不能基於它實例化一個模板。

請記住:模板是類型。類型必須在編譯時確定。

您可能應該將成員指針作爲參數傳遞給Bind函數。

1

我不太確定你想達到什麼目的?

如果MemberFunctionPointer是一個變量,在編譯時它的值是未知的,例如,可能取決於某些用戶行爲 - 那麼它不能用作模板參數。

另一方面,如果可以在編譯時實際推導出MemberFunctionPointer,則應該將它作爲模板參數傳遞,而不是函數參數。考慮下面的例子:

(在第一種情況下使用Bindcall;在第二種情況下,使用StaticBindcallStatic

#include <stdio.h> 

class X { 
    public: 
    int x; 
    void foo() {printf("foo\n");} 
    void bar() {printf("bar\n");} 
}; 

template <typename T> 
class SomeClass { 
    public: 
    static void Bind(void (T::*MemberFunctionPointer)(), T *obj) { 
     (obj->*MemberFunctionPointer)(); 
    } 
    template <void (T::*MemberFunctionPointer)()> 
    static void StaticBind(T *obj) { 
     (obj->*MemberFunctionPointer)(); 
    } 
}; 

template <class C> 
static inline void call(void (C::*MemberFunctionPointer)(), C *obj) { 
    SomeClass<C>::Bind(MemberFunctionPointer,obj); 
} 

template <class C, void (C::*MemberFunctionPointer)()> 
static inline void callStatic(C *obj) { 
    SomeClass<C>::template StaticBind<MemberFunctionPointer>(obj); 
} 

int main() { 
    X obj; 
    call<X>(&X::foo,&obj); 
    callStatic<X,&X::bar>(&obj); 
    return 0; 
} 
+0

我想在編譯時推導它,但我不知道如何。所以第二種情況更適合......只是我試圖提供一個不帶任何模板參數的方法「調用」。 – Mirco

+0

在這種情況下,您可以實際使用第一種方法,再加上內聯所有功能。但是,如示例所示,綁定函數必須通過參數獲取成員函數指針,而不是通過模板參數。隨着優化打開,它應該歸結爲一個常數,你應該體驗沒有運行時間的開銷。函數'call'的參數''實際上可以從傳遞的參數中推導出來,因此實際上可以在調用中跳過它。爲了清楚起見,我在那裏給了它 – CygnusX1

1

模板參數具有在編譯時是已知的。作爲函數參數的指針變量的內容取決於該函數的調用方式。這在編譯時是不知道的!

如果你知道這個指針在編譯時已經,你可以把函數指針運行參數爲模板參數:

template<class T_CLASS, void(T_CLASS::*MemFunPtr)()> 
void Example(T_CLASS* InstancePointer) {...} 

這裏,MemFunPtr是在編譯時和已知的模板參數因此可以作爲另一個功能或類模板的模板參數...

+0

謝謝,這就是我想要做的。據我瞭解你沒有機會將MemFunPtr作爲普通參數傳遞,並避免將它作爲模板參數傳遞給Example,對吧? – Mirco

+0

是的,沒錯。 – sellibitze

相關問題