5

假設我想開發一個通用庫,該類庫應該可用於數字類型類型,包括double類型和用戶定義類型。 ,我面對現在的問題是,我不知道如何編寫一個函數模板的返回類型很多像這樣的:對於基本類型,確定「通用函數」的返回類型

template<class T> 
auto transmogrify(T x) 
-> ??? 
{ 
    using std::abs; 
    return abs(x)+2.0; 
} 

using聲明使得這個函數模板的機身做工因爲這些沒有關聯的命名空間(因此沒有ADL)。但我希望transmogrify在用戶定義類型的作者提供自己的abs函數的情況下使用專用的abs函數。我不能簡單地用

-> decltype(abs(x)+2.0) 

,因爲這不會,比如說,加倍工作,因爲的std :: ABS是不是在範圍(據我可以告訴)。但寫作

-> decltype(std::abs(x)+2.0) 

將禁用ADL。但禁用ADL不是一種選擇。另外,由專門的abs函數返回的值可能不是T類型,而是其他類型。

關於如何解決返回類型問題的任何想法,同時(a)保持ADL和(b)對於不提供專門的abs的類型,在某些默認函數(如std :: abs) 。

+0

'#define ab using std :: abs; your_template_fn #undef ab'不知道如果這個好的選擇 –

+0

任何人都可以評論上面的事情是好還是不好? –

+1

@Anubis先生以及如何確定返回類型的函數使用這個定義? – ForEveR

回答

12

使用單獨的命名空間,您可以在其中放置using子句。這可以防止名稱空間污染,因爲using子句只適用於該名稱空間。我會推薦給它命名一些獨特的東西,所以你不會意外地傳播它。

namespace transmog_detail 
{ 
    using std::abs; 

    template<class T> 
    auto transmogrify(T x) -> decltype(abs(x) + 2.0) 
    { 
     return abs(x) + 2.0; 
    } 
} 

// Then pull it into the current namespace, as recommended by @LucDanton. 
using transmog_detail::transmogrify; 

// Or if there is a reason, you can forward. 
// template<class T> 
// auto transmogrify(T x) 
// -> decltype(transmog_detail::transmogrify(x)) 
// { 
// return transmog_detail::transmogrify(x); 
// } 
+0

非常聰明!未命名的命名空間可能會或可能不會使這個更清潔。不確定。 –

+0

當然! :)謝謝,戴夫! – sellibitze

+0

@MooingDuck:可能,也可能不會。如果您使用任何其他未命名的名稱空間,則它們也將具有使用子句,這可能不合意。 –

-6

上面的答案很好,但我能想到的模擬方式是使用typeinfo頭。它是專門爲確定對象的類型和構造函數而設計的。

see here:http://www.cplusplus.com/reference/std/typeinfo/type_info/

+4

-1沒有任何用處 - type_info是關於運行時類型標識的,而聲明需要一個靜態確定的類型。 –