2014-01-23 204 views
1

我有這種類型的功能:我想他們包裹裏面是這樣另一個模板函數C++返回模板函數

type uniRndtype() 
{ 
    return typeValue; 
} 

現在:

template<typename T> 
T(* uniRndType(void))() 
{ 
    if (is_same<T, bool>::value) 
    { 
     return uniRndBool; 
    } else if (is_same<T, char>::value) 
    { 
     return uniRndChar; 
    } else 
    ... 
} 

,並調用它像這樣:

uniRndType<int>(); 

但我發現了一個錯誤:「錯誤:返回值類型不匹配日e功能類型「 ,因爲每個返回都有不同的類型。

我有一種方法可以使它工作嗎?因爲從運行時的角度來看,我沒有看到任何錯誤,只有編譯器有問題。

+0

使用'static_cast'將函數強制轉換爲返回類型。 – Barmar

+2

您似乎混合了編譯時和運行時後勤。 T由調用者在編譯時預先確定;不是運行時間 – WhozCraig

+0

錯誤是因爲所有返回類型必須與'T'兼容才能實現該方法。如果你用一個字符串調用它,'uniRndType ()'那麼編譯器如何處理你得到的返回一個布爾值的代碼? – Sean

回答

3

問題是,雖然優化器可以消除死代碼分支,但前端(詞法,語法分析&)不能。這意味着模板實例化中的所有代碼都必須是有效的。也就是說,即使在這樣的:

if (is_same<T, bool>::value) 
{ 
    return uniRndBool; 
} 

身體將永遠不會被執行時Tchar,它仍然必須是有效的C++代碼。當然不是,因爲uniRndBool沒有正確的類型。

你有兩種選擇:在你的特定情況下工作的黑客,和一個通用的。

在所有return語句中,hacker將使用reinterpret_cast<T(*)()>。對於正確的T brach,它將是一個無操作。其他分支永遠不會在運行時執行,所以一切都會好的。

另一種解決方案是使用模板專業化。由於它是一個bad idea to specialise function templates,你可以使用衆所周知的「代表類」技巧:

template <class T> 
struct uniRndTypeHelper; 

template <> 
struct uniRndTypeHelper<bool> 
{ 
    static bool (*get())() { return uniRndBool; } 
}; 

template <> 
struct uniRndTypeHelper<char> 
{ 
    static char (*get())() { return uniRndChar; } 
}; 

template<typename T> 
T(* uniRndType(void))() 
{ 
    return uniRndTypeHelper<T>::get(); 
} 
+0

+1。我同意你,但是......這很麻煩zz – ikh

1
template <typename T> T (*uniRndType())() 
{ 
    //else 
    ... 
} 

template <> bool (*uniRndType())() 
{ 
    return uniRndBool; 
} 

template <> char (*uniRndType())() 
{ 
    return uniRndChar; 
} 

就是這樣。

編輯:原則上,我們必須像@Angew那樣做。但它有點麻煩

+0

所以第二個和第三個函數是重載的,但是第一個是什麼?刪除它會導致錯誤,但同時它的空... – Vladp

+0

@Vladp這些不是函數重載,但功能模板專業化。 – ikh

0

這是行不通的,因爲當編譯器擴展給定類型的模板方法時,該方法必須是有效的。您的類型T需要與列出的所有退貨類型兼容,例如bool,char等。正如我在評論中提到的,如果您通過std::string,您不希望該方法起作用,對嗎?

解決這個問題的方法之一是使用template specialization來表示每種類型需要什麼。

0

編譯器需要知道函數/方法在編譯時將使用哪些類型。此時,您必須使用它可能接收的類型作爲模板參數來實例化此模板函數,如@ikh在此處所寫。

但是,如果你使用的是帶有模板方法模板類,你有2種方式:

1)簡單地寫在實現.h文件中(右的地方,你聲明模板類身體每個模板的方法)而不僅僅是原型;

2)或者在.h文件中聲明原型之後,您需要使用可能接收的模板參數來安裝此模板類。