2014-05-02 35 views
3

我明白轉發如何完善在通常情況下工作:如果不使用SFINAE或編寫多個版本,是否可以完美地轉發「非泛型」類型?

template <typename T> 
void f(T &&arg) { 
    E(std::forward<T>(arg))); 
} 

是否有可能完全向前「非通用」類型,如某種形式的std::string不使用SFINAE或寫多個版本?

/* Likely some kind of template. */ 
/* template <typename T> */ 
void f(/* Something goes here*/ arg) { 
    E(std::forward</* Something goes here. */>(arg); 
} 

下應該是真實的:

f(std_str_obj); // Lvalue forwarded as const lvalue ref. 
f("hello"); // Temporary forwarded as rvalue reference. 
f(1); // Error, not a std::string or convertible to std::string. 

我懷疑,唯一的辦法是仍編寫一個函數模板,並使用某種形式的SFINAE來限制它(在這種情況下,我可以找出自己的東西),但我想知道是否有一些簡單的方法,我錯過了。

+1

'void f(std :: string && arg){E(std :: forward (arg));}'應該這樣做。 –

+3

@RSahu:那不會接受一個左值。 –

+0

'void f(std :: string arg)'應該這樣做。 –

回答

0

除非我錯過了某些東西,否則這應該適用於您正在尋找的東西。

void f(std::string&& arg) // Take care of rvalues 
{ 
    E(std::forward<std::string&&>(arg)); 
} 

void f(std::string const& arg) // Take care of lvalues 
{ 
    E(std::forward<std::string const&>(arg)); 
} 

我能夠測試使用下列程序:

#include <iostream> 
#include <string> 
#include <utility> 

void E(std::string const& s) 
{ 
    std::cout << "Came to E(std::string const&)\n"; 
} 

void E(std::string&& s) 
{ 
    std::cout << "Came to E(std::string&&)\n"; 
} 

void f(std::string&& arg) // Take care of rvalues 
{ 
    E(std::forward<std::string&&>(arg)); 
} 

void f(std::string const& arg) // Take care of lvalues 
{ 
    E(std::forward<std::string const&>(arg)); 
} 

int main() 
{ 
    std::string s1("abcd"); 
    f(s1); 
    f("xyx"); 
} 

輸出我從運行的程序有:

 
Came to E(std::string const&) 
Came to E(std::string&&) 

更新

更換兩個帶過載的f的重載實現一個函數模板也可以工作。

template <typename T> 
void f(T&& arg) 
{ 
    E(std::forward<T>(arg)); 
} 

int main() 
{ 
    std::string s1("abcd"); 
    f(s1); 
    f("xyx"); 
} 

如果我添加f(1)main,有一個編譯器錯誤,因爲有沒有E重載可以與工作。如果E本身是一個函數模板,則該策略將不起作用。

我認爲,你必須防止除std::string之外的其他任何東西的使用能力,只能在f級別或E級別處理這些類型。

+1

是的,這是我知道可以工作的多個版本。沒關係,只是想知道是否有辦法做到這一點。 – kec

+2

'std :: forward'只能與模板參數一起使用,否則它的行爲與std :: move相同。你應該使用'std :: move'而不是'std :: forward'。 –

+0

@XinHuang:儘管如此,他應該不使用'std :: move'作爲左值版本。這個論點應該簡單地傳遞給別人。 – Xeo

1

不,這樣的事情是不可能的。

如果你的函數只需要一個指定的類型,那麼最好的辦法就是創建兩個函數,而不是試圖用技巧來超越語言。

如果您使用模板,那麼f(1);會將int設置爲模板參數。那不是你想要的。

0
#include <utility> 
#include <type_traits> 

template < 
    class T 
    , class = typename std::enable_if< 
     std::is_convertible<std::decay_t<T>, std::string const&>::value 
     || std::is_convertible<std::decay_t<T>, std::string  &&>::value 
    >::type 
> 
void f (T&& t) { E (std::forward<T> (t)); } 
相關問題