2012-06-06 77 views
3

std::reference_wrapper使用指針下方的指針來存儲「引用」,我試圖做類似於下面的代碼。std :: enable_if與std :: is_reference無法編譯

#include <type_traits> 

struct Foo 
{ 
    void* _ptr; 

    template<typename T> 
    Foo(T val, 
     typename std::enable_if 
      < 
       std::is_reference<T>::value, 
       void 
      >::type* = nullptr) 
     : _ptr(&val) 
    { } 
}; 

int main() 
{ 
    int i = 0; 
    int& l = i; 

    Foo u2(l); 

    return 0; 
} 

然而,這無法編譯:

CXX main.cpp 
main.cpp: In function ‘int main()’: 
main.cpp:23:13: error: no matching function for call to ‘Foo::Foo(int&)’ 
main.cpp:23:13: note: candidates are: 
main.cpp:8:5: note: template<class T> Foo::Foo(T, typename std::enable_if<std::is_reference<_Tp>::value, void>::type*) 
main.cpp:8:5: note: template argument deduction/substitution failed: 
main.cpp: In substitution of ‘template<class T> Foo::Foo(T, typename std::enable_if<std::is_reference<_Tp>::value, void>::type*) [with T = int]’: 
main.cpp:23:13: required from here 
main.cpp:8:5: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’ 
main.cpp:3:8: note: constexpr Foo::Foo(const Foo&) 
main.cpp:3:8: note: no known conversion for argument 1 from ‘int’ to ‘const Foo&’ 
main.cpp:3:8: note: constexpr Foo::Foo(Foo&&) 
main.cpp:3:8: note: no known conversion for argument 1 from ‘int’ to ‘Foo&&’ 

我怎樣才能爲參考參數enable_if回是真的嗎?

+0

顯而易見的答案是在_is_reference &&!is_integral_上進行條件化,並且與之相反,它的工作原理但不是一個好的答案... –

+0

@ K-ballo我已簡化了我的問題,並將編輯問題以更加準確反射問題 - 這是如何讓'enable_if 對引用有效 –

回答

5

T在這種情況下永遠不會被推斷爲引用類型。在構建對象u2時,構造函數模板參數推導爲int

雖然可變u2的類型是int&,當你在表達式中使用u2,它是int類型的左值表達式。 An expression never has reference type.

模板參數推導使用函數參數的類型來推導模板參數類型。函數參數是表達式。因此,由於沒有表達式具有引用類型,所以模板參數永遠不會被推斷爲引用類型。

[在C++ 11中,如果函數參數的類型爲T&&,T可能推導爲類型T&如果參數是一個左值。這種機制可以完美轉發。不過,這與您的場景無關。]

實際上,在表達式中,對象和對該對象的引用是無法區分的。引用只允許您爲對象提供其他名稱。

+0

James,這是一個更復雜的代碼片段的一部分,我試圖用'enable_if'來區分整數,指針和l值參考。因此,我試圖做甚至可能使用'enable_if'? –

+0

不,因爲[表達式從來沒有引用類型](http://stackoverflow.com/a/10238252/151292)。爲什麼你認爲你需要區分「對象的引用」和「對象」? –

+0

我想使用聯合來存儲不同的數據類型 - 如果它是整數類型的,我將值本身存儲在'union :: uint64_t'成員中,如果它是一個指針,我將值本身存儲在聯合:: void *'成員,如果它是一個引用,則在'union :: void *'成員中存儲引用的**地址**。我想重載聯合構造函數來使用模板參數推導來知道如何處理輸入參數 –

相關問題