2011-12-20 48 views
10

假設我有兩個struct S:完美轉發對象的成員

struct X {}; 
struct Y { X x; } 

我具備的功能:

void f(X&); 
void f(X&&); 

我怎樣寫一個函數g()這需要Y&Y&&但完美轉發X&X&&f(),分別爲:

template <typename T> 
void g(T&& t) { 
    if (is_lvalue_reference<T>::value) { 
    f(t.x); 
    } else { 
    f(move(t.x)); 
    } 
} 

上面的代碼說明了我的意圖,但隨着參數數量的增長,它的擴展性不是很好。有沒有辦法使它完美轉發並使其可擴展?

+0

我想改變'is_lvalue_reference :: value'到'is_lvalue_reference (T) )> :: value'將會有你想要的語義,但是我認爲你想要的語義是有問題的...... – ildjarn 2011-12-20 04:08:10

+0

(對不起,這個拙劣的答案)我會說它不縮放的原因是因爲設計是可疑的開始。 「移動」子對象意味着什麼?這在什麼狀態下離開主要目標?即使有一種簡單的方法來編寫它,它看起來像結構不良的代碼... – 2011-12-20 04:12:08

回答

15
template <typename T> 
void g(T&& t) { 
    f(std::forward<T>(t).x); 
} 
+1

對我來說很好看http://ideone.com/Edf4o – 2011-12-22 20:40:52

+0

更好的解決方案,但爲什麼它工作? – Pubby 2011-12-22 20:50:53

+0

@Pubby,因爲'rvalue.foo'是一個右值。我可以想到爲什麼它可能是有意義的(如果容器的壽命很短並且是一個右值,那麼被包含的對象也會分享這個屬性),但是我對這些哲學並不熟悉,所以我不知道其理由,所以我對此無能爲力。 – 2011-12-22 20:58:27

3

我認爲這會工作,雖然我不知道:

template<class T, class M> 
struct mforward { 
    using type = M&&; 
}; 
template<class T, class M> 
struct mforward<T&, M> { 
    using type = M&; 
}; 

template <typename T> 
void g(T&& t) { 
    f(std::forward<typename mforward<T, decltype(t.x)>::type>(t.x)); 
} 
+2

+1我必須在libC++中解決幾乎這個確切的問題。我提出的解決方案與Pubby的解決方案非常相似。我不僅想把'T'的l/r值「應用」到'M',我還想將'T'的cv-qualifications應用於'M'。我發現應用程序超越數據成員。爲了好奇,我把它稱爲'__apply_cv',它是開源代碼:http://libcxx.llvm.org/ – 2011-12-20 14:25:18

+0

@霍華德看到了我的答案。或者我錯過了什麼? – 2011-12-22 20:15:09

+0

也@Howard談論簡歷資格讓我想到這個答案的缺陷。 'decltype(t.x)'只給你聲明的'x'類型。如果'T'是'const',但'x'被聲明爲'int a',那麼你的轉發就會嘗試以'int&'/'int &&'的形式轉發。你需要說一些類似於'typename remove_reference > type'來考慮't'的常量。這也考慮到了'mutable'成員,但我不知道什麼樣的移動在哲學上意味着一個其他'const'對象的可變成員。 – 2011-12-22 20:30:54