3

我已經制作了is_iterable模板,如下所示 - 它檢查自由函數begin/end是否可用(在ADL的上下文中)並返回適當的迭代器對象。 (這是在遠程-for循環迭代對象的要求)在GCCADL在特定情況下不起作用

#include <utility> 
#include <iterator> 
#include <type_traits> 
#include <vector> 

template <typename T> 
typename std::add_rvalue_reference<T>::type declval(); // vs2010 does not support std::declval - workaround 

template <bool b> 
struct error_if_false; 

template <> 
struct error_if_false<true> 
{ 
}; 

template<typename U> 
struct is_input_iterator 
{ 
    enum { 
     value = std::is_base_of< 
      std::input_iterator_tag, 
      typename std::iterator_traits<U>::iterator_category 
     >::value 
    }; 
}; 

template<typename T> 
struct is_iterable 
{ 
    typedef char yes; 
    typedef char (&no)[2]; 

    template<typename U> 
    static auto check(U*) -> decltype(
     error_if_false< 
      is_input_iterator<decltype(begin(declval<U>()))>::value 
     >(), 
     error_if_false< 
      is_input_iterator<decltype(end(declval<U>()))>::value 
     >(), 
     error_if_false< 
      std::is_same< 
       decltype(begin(declval<U>())), 
       decltype(end(declval<U>())) 
      >::value 
     >(), 
     yes() 
    ); 

    template<typename> 
    static no check(...); 

public: 
    static const bool value = (sizeof(check<typename std::decay<T>::type>(nullptr)) == sizeof(yes)); 
}; 

#include <cstdio> 
void write(int a) 
{ 
    printf("%d\n", a); 
} 

template<typename T> 
typename std::enable_if<is_iterable<T>::value>::type write(const T& a) 
{ 
    for (auto i = begin(a), e = end(a); i != e; ++i) { 
     write(*i); 
    } 
} 

int main() 
{ 
    write(10); 

    std::vector<int> a; 
    a.push_back(1); 
    a.push_back(2); 
    a.push_back(3); 
    a.push_back(4); 

    write(a); 
} 

以上代碼完全按預期工作在VS2010,但不是。而且,當我把一些名爲'begin'的隨機免費函數,如下所示,即使在vs2010中它也會被破壞。

int begin(int) 
{ 
} 

如何讓代碼有效?此外,任何改善「is_iterable」概念檢查的建議將不勝感激。

補充說:「寫」功能只是一個概念演示的例子 - 請不要把寶貴的時間投入到它。 (我知道這不是最好的代碼:()該部分需要一些注意的是ADL行爲和「is_iterable」模板:)

+1

我對提高代碼將是建議:「只要使用'STD :: copy(a.begin(),a.end(),std :: ostream_iterator (std :: cout,「\ n」));'而不是'write(a);',並且消除其餘部分代碼。」這將適用於任何定義'operator <<'的類型,而不僅僅是那些爲'write'定義了重載的類型。 – 2012-07-08 14:18:47

+1

感謝您的反饋,但我不認爲「寫」或「運營商」是否重要 - 「is_iterable」概念檢查機制是我的觀點。 「寫」只是最簡單的例子:( – summerlight 2012-07-08 15:46:53

+1

相關:http://stackoverflow.com/questions/9838862/why-koenig-lookup-doesnt-work-with-function-template-dynamic-pointer-cast – 2012-07-08 15:53:30

回答

0

加入std::begin/end後 - 你的代碼編譯和下運行GCC-4.6

改進建議:替換爲error_if_falseenable_if

-1

write(a);應該通過運營商定義爲傑瑞說。也許讓它更簡潔,讓你的代碼更乾淨。

+0

歡迎來到StackOverflow!你的回答會更好的評論它真的沒有專門回答OP的問題。 – 2012-07-08 17:37:44

+0

@Bob Kaufman他確實沒有50分,他不能發表評論 – benRollag 2012-07-08 17:54:53

+0

@benRollag,謝謝你的提醒,通常我設法讓自己在這個問題上有所收穫 – 2012-07-08 17:57:41

相關問題