解决方法
遗憾的是,没有标准的方法来检测一个类是否为Iterator模型.最简单的检查是*它和它在语法上都是有效的;你可以使用标准的SFINAE技术做到这一点:
template<typename T,typename = decltype(*std::declval<T&>(),void(),++std::declval<T&>(),void())> MyClass(T);
考虑24.2.2:2中的迭代器要求:
template<typename T> typename std::enable_if< !std::is_void<decltype(*std::declval<T &>())>::value && std::is_same<decltype(++std::declval<T &>()),typename std::add_lvalue_reference<T>::type>::value,std::true_type>::type has_iterator_requirements_helper(int); template<typename T> std::false_type has_iterator_requirements_helper(...); template<typename T> struct has_iterator_requirements: decltype(has_iterator_requirements_helper<T>(0)) {}; template<typename,bool> struct is_iterator_check: std::false_type {}; template<typename T> struct is_iterator_check<T,true>: std::true_type { typedef typename std::iterator_traits<T>::difference_type difference_type; typedef typename std::iterator_traits<T>::value_type value_type; typedef typename std::iterator_traits<T>::iterator_category iterator_category; typedef typename std::iterator_traits<T>::reference reference; typedef typename std::iterator_traits<T>::pointer pointer; static_assert(std::is_same<decltype(*std::declval<T &>()),reference>::value || std::is_void<reference>::value,"*r must be of type reference"); }; template<typename T> struct is_iterator: is_iterator_check<T,(std::is_pointer<T>::value && !std::is_void<typename std::remove_pointer<T>::type>::value && !std::is_function<typename std::remove_pointer<T>::type>::value ) || (std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value && std::is_nothrow_destructible<T>::value // Todo: check lvalues are swappable && has_iterator_requirements<T>::value )> {};
尝试使用iterator_traits的问题在于它是为所有类型定义的模板,并且其实例化将在非SFINAE上下文中失败(回想一下SFINAE仅适用于直接替换失败). libstdc有一个conforming extension,在非迭代器类型上实例化iterator_traits会产生一个空类型;你可以通过检查类型上是否存在iterator_category来做类似的技巧:
template<typename T> std::true_type has_iterator_category_helper( T::iterator_category *); template<typename T> std::false_type has_iterator_category_helper(...); template<typename T> struct has_iterator_category<T>: decltype(has_iterator_category_helper<T>(0)) { }; template<typename T> struct is_iterator: std::integral_constant<bool,std::is_pointer<T>::value || has_iterator_category<T>::value> {}; template<typename T,typename = std::enable_if<is_iterator<T>::value>> MyClass(T);
但是,这对于那些本身不公开iterator_category但已经通过单独的iterator_traits特化进行调整的类型不起作用;在这种情况下,简单的SFINAE方法更有意义(并且您可以在构造函数中实例化iterator_traits以确认类型是类迭代器).
原文地址:https://www.jb51.cc/c/110585.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。