9

如何特殊化採用通用參考參數的函數模板?指定採用通用參考參數的函數模板

foo.hpp:

template<typename T> 
void foo(T && t) // universal reference parameter 

Foo.cpp中

template<> 
void foo<Class>(Class && class) { 
    // do something complicated 
} 

這裏,Class不再是推導的類型,因此是準確Class;它不可能是Class &,所以參考摺疊規則在這裏不會幫助我。我可以創建另一個採用參數Class &的參數(我不確定),但這意味着要複製foo中包含的所有代碼,以獲取所有參數的rvalue/lvalue引用的每種可能組合,這是通用引用的假設避免。

有沒有辦法做到這一點?

更具體談談我的問題的情況下,有一個更好的辦法來解決這個問題:

我有一個可以連接到多個遊戲服務器程序,每個服務器,在大多數情況下,調用由一切同名。但是,它們的幾個版本略有不同。有幾個不同的類別,這些東西可以是:移動,項目等。我寫了一個通用的「移動字符串來移動枚舉」功能的內部代碼調用,並且我的服務器接口代碼也有類似功能。但是,有些服務器有自己的內部ID,它們可以通信,有些使用字符串,有些使用兩種情況。

現在我想要做的是讓這個更通用一點。

我想打電話給ServerNamespace::server_cast<Destination>(source)。這將允許我從Move轉換到std::stringServerMoveID。在內部,我可能需要複製(或從中移出),因爲有些服務器要求我保留已發送消息的歷史記錄。通用參考似乎是這個問題的明顯解決方案。

頭文件我在想,現在只想這暴露:

namespace ServerNamespace { 

template<typename Destination, typename Source> 
Destination server_cast(Source && source); 

} 

和實現文件將定義所有合法的轉換爲模板特。

+1

應該'f'是'foo'?此外,問題的背景是什麼?你通常需要重載,而不是專門化。 – GManNickG

+0

@GManNickG也許我使用了錯誤的術語。我已經編輯了我的問題,並詳細說明了我正在努力完成的任務 –

+0

對於關於此問題的非常好的文章,請參閱:https://mortoray.com/2013/06/03/overriding-the-broken-universal-reference -t/ –

回答

2

在我看來,最好的解決辦法是,你對超載的標籤,而不是實際的類型使用標籤調度系統:

struct foo { 
    struct tag {}; 
}; 

struct bar { 
    struct tag {}; 
}; 

template<typename Destination, typename Source> 
Destination server_cast(Source && source, foo::tag) { 
    // foo 
} 

template<typename Destination, typename Source> 
Destination server_cast(Source && source, bar::tag) { 
    // bar 
} 

template<typename Destination, typename Source> 
Destination server_cast(Source && source) { 
    return server_cast<Destination>(std::forward<Source>(source), typename std::remove_reference<Source>::type::tag()); 
} 
+0

我得多想一想。 –

1

最具擴展性的事情就是創建一個模板類專業化。

template< class X > struct Whatever { 
    void f(){ ... } 
}; 

template<> struct Whatever<UserType> { 
    void f(){ ... } 
}; 

我說這是最具擴展性的原因是因爲您可以在定義任何內容的文件內部或外部的任何地方添加專門化。

這是對Pubby建議的標籤分發解決方案的免費而不是排他性的。