我已经制作了如下的is_iterable模板 - 它检查自由函数的开始/结束是否可用(在ADL的上下文中)并返回正确的迭代器对象。 (这是ranged-for循环中可迭代对象的要求)
#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中的预期工作,但不是在gcc中。而且,当我把一些名为'begin'的随机自由函数放在下面时,即使在vs2010中它也会被破坏。
int begin(int)
{
}
如何使代码有效?此外,任何改进“is_iterable”概念检查器的建议都将受到赞赏。
补充说:“写”功能只是一个概念演示示例 - 请不要把宝贵的时间花在它上面。 (我知道这不是最好的代码:()需要注意的部分是ADL行为和“is_iterable”模板:)
答案 0 :(得分:0)
将std::
添加到begin
/ end
后,您的代码将在gcc-4.6
改进建议:将error_if_false
替换为enable_if
答案 1 :(得分:-1)
write(a);
。也许让它更加简洁,以便你的代码更清晰。