2010-09-17 65 views
1

我在stackoverflow上搜索了一段時間,但是我不明白模板足以找到解決方案,或者它根本沒有被回答過。要求函數模板的返回類型是模板的專門化

在這個例子中:

template <typename T> T f(); 

是否有可能使功能需要類型T是std::basic_string模板的一個特例?

我可以將模板和T定義爲std::basic_string的類型,所以(使用std::basic_string<T>內部,當然):

template <typename T> std::basic_string<T> f(); 

但我不能夠通過std::stringstd::wstring到函數(期望返回類型分別爲std::stringstd::wstring),這是這裏的真正目標(能夠傳遞來自std::basic_string模板的任何類型)。

+0

@ splash請指出您是指「派生自」還是「專業化」。在你原來的帖子中你說過「源自」。 Potatoswatter將其標題改爲「專業化」,但只留下了主要內容。你的真實意圖是什麼?請修復你的問題。你最後一段對我來說就像「我不能傳遞std :: string,因爲它看起來像'std :: basic_string '。」。它不一定跟隨你的正文,你的意思是什麼。 – 2010-09-17 11:01:16

+0

如果我理解術語,我會用'專業化'。你甚至可以從模板類派生嗎? – komiga 2010-09-17 12:00:53

+0

@ splash謝謝,現在很清楚。同理,我會解釋「derived from basic_string」,因爲這個類來自'basic_string '。所以從某種意義上說,它是不明確的:) – 2010-09-17 12:09:53

回答

8

部分專業化可以讓您測試一個類型是否是特定模板的專業化。 SFINAE是一種可以「關閉」函數模板聲明的技巧。解決方案結合了這些技術。

template< typename T > // by default, 
struct enable_if_basic_string {}; // a type is not a basic_string 

template< typename CharT, typename Traits > 
struct enable_if_basic_string< basic_string< CharT, Traits > > { 
    typedef basic_string< CharT, Traits > type; // same as argument type 
}; 

// enable_if_basic_string<>::type exists only if T specializes basic_string 
// if not, compiler ignores function declaration per SFINAE. 
template< typename T > 
typename enable_if_basic_string<T>::type 
F() { 
    ..... 
} 

如果你的意思是推導,以及專業化,你可以看看std::tr1::is_convertibleenable_if爲好。

+0

+1 - 它絕對解決了這個問題。不幸的是,它也要求你用無用的參數來裝飾函數,不過幸好可以用默認參數隱藏。 – Paul 2010-09-17 06:40:37

+0

@Paul:不,那裏沒有參數。我根本沒有改變他的函數的模板或運行時參數。 – Potatoswatter 2010-09-17 06:48:15

+0

@Patatoswatter:是的,對於這個應用程序。當你已經有一個返回類型時,我指的是使用這個習慣用法。對不起,我不清楚。 – Paul 2010-09-17 06:54:11

1

這在vanilla C++中是不可能的。有一種針對C++ 0x的語言結構,可能會導致這種情況,不幸的是它被丟棄了。

你可以這樣做在一定程度上與Boost概念檢查庫,但是:http://www.boost.org/doc/libs/1_44_0/libs/concept_check/concept_check.htm

+0

我不能評論詹姆斯麥克奈利斯的帖子,因爲一些無用的聲望要求,所以我會在這裏說一下:我是堆棧溢出的新手,我在回答問題時通常會看到的一個趨勢是實際上沒有回答這個問題,但是卻忽略了這個問題。這是堆棧溢出的正常情況嗎,還是我只是決定在錯誤的時間加入? – Paul 2010-09-17 05:57:16

+0

鄧諾。我經常不在這裏。 我知道我永遠不會使用Boost。你的回答確實回答了我的問題,但沒有給我一個解決方案。 – komiga 2010-09-17 06:18:54

+0

是否有您選擇不使用助推的特定原因,還是因工作原因而受到限制? 編輯:此外,在上面發佈的註釋代碼中,請考慮儘可能使用引用,並且只有在需要特定功能時纔會還原爲指針。 – Paul 2010-09-17 06:21:43

5

而是要求Tstd::basic_string一個專業化的,爲什麼不假設Tstd::basic_string專業化如果不是,則讓模板實例化失敗。只需使用您需要的std::basic_string

例如,

template <typename T> 
T get_first_three_chars(const T& str) { return str.substr(0, 3); } 

在這裏,我們假定T具有一個成員函數substr;如果沒有,那麼實例化將失敗,導致編譯錯誤。

+0

嗯。這看起來如何? http://pastebin.com/xiL8TGSn 我認爲我不應該使用字符串指針,但它會編譯。編輯:劃痕。這適用於我所需要的:http://pastebin.com/kptMXUPL 任何東西看起來都不對? – komiga 2010-09-17 06:16:18

+0

除了它是指針而不是引用,是..由於某種原因,我不能再編輯該評論,所以這裏是我留下的:http://pastebin.com/6yQdTWYV – komiga 2010-09-17 06:31:44

+0

@ splash:你可以編輯評論僅限於5分鐘的寬限期。 – sbi 2010-09-17 08:12:03