2011-04-15 49 views
4

我最近開始使用右值引用,我遇到了一個情況,我不明白他們爲什麼以他們的方式工作。Rvalue引用和SFINAE

我試圖確定一個類型是否可以調用beginend。下面的代碼給出了預期的結果,如果我通過值或const引用更改foo來接受它的參數,但我不確定爲什麼它在使用右值引用時不起作用,我想知道是否有人能告訴我爲什麼。

#include <vector> 
#include <type_traits> 
#include <iostream> 

template<class Container> 
auto begin(Container &&c) -> decltype(c.begin()) { return c.begin(); } 

template<class Container> 
auto end(Container &&c) -> decltype(c.end()) { return c.end(); } 

template<class T, size_t size> 
T *begin(T (&array)[size]) { return (&array[0]); } 

template<class T, size_t size> 
T *end(T (&array)[size]) { return (&array[0] + size); } 

template <typename T> 
struct has_begin_end 
{ 
    typedef char true_type; 
    typedef char false_type[2]; 

    template <typename U> static true_type& test(decltype(begin(*((U*)0))) *b = 0, 
               decltype(end(*((U*)0))) *e = 0); 

    template <typename U> static false_type& test(...); 

    enum { value = (sizeof(true_type) == sizeof test<T>(0)) }; 
}; 

template<class T> 
void foo(T &&t) 
{ 
    std::cout << has_begin_end<T>::value << std::endl; 
} 

int main() 
{ 
    std::vector<int> v = {1, 2}; 

    std::cout << has_begin_end<std::vector<int> >::value << std::endl; 
    std::cout << has_begin_end<int>::value << std::endl; 

    foo(v); 
    foo(123); 
} 
+2

而不是'*((U *)0)',使用'std :: declval ()'。 – GManNickG 2011-04-15 18:38:24

+0

謝謝GMan。看起來我在閱讀新的C++ 0x功能時忽略了declval。 – Adam 2011-04-15 18:55:15

回答

6

這是因爲當用左值調用foo時,T被推導爲左值引用類型。嘗試:

has_begin_end<typename remove_reference<T>::type>::value