我已經制作了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」模板:)
我對提高代碼將是建議:「只要使用'STD :: copy(a.begin(),a.end(),std :: ostream_iterator(std :: cout,「\ n」));'而不是'write(a);',並且消除其餘部分代碼。」這將適用於任何定義'operator <<'的類型,而不僅僅是那些爲'write'定義了重載的類型。 –
2012-07-08 14:18:47
感謝您的反饋,但我不認爲「寫」或「運營商」是否重要 - 「is_iterable」概念檢查機制是我的觀點。 「寫」只是最簡單的例子:( – summerlight 2012-07-08 15:46:53
相關:http://stackoverflow.com/questions/9838862/why-koenig-lookup-doesnt-work-with-function-template-dynamic-pointer-cast – 2012-07-08 15:53:30