对于日志记录代码,我想检测模板函数的给定参数是否可以使用以下工具进行迭代升压范围 http://www.boost.org/libs/range/doc/html/index.html或不。显然,无论是否,我都需要实例化不同的代码,所以我需要 SFINAE,可能(好吧,当然)与 boost::enable_if 结合使用。我试过检测是否begin
and end
自由函数的定义如下:
namespace is_range_impl {
template <typename T> T &make();
struct any { template <class T> any(T const&); };
struct not_range {};
not_range begin(const any &);
not_range end(const any &);
struct no_type { char x[8]; };
typedef char yes_type;
template <typename T> yes_type check(const T &t);
no_type check(const not_range &t);
using boost::begin;
using boost::end;
template <typename T> struct is_range_impl {
enum e {
value = (sizeof(check(begin(make<T>()))) == sizeof(yes_type) &&
sizeof(check(end(make<T>()))) == sizeof(yes_type)),
};
};
}
template <typename T>
struct is_range : public is_range_impl::is_range_impl<T> {};
template <typename T>
typename boost::disable_if<is_range<T> >::type repr(std::ostream &s, const T &v)
{ ... }
template <typename T>
typename boost::enable_if<is_range<T> >::type repr(std::ostream &s, const T &v)
{ ... }
但不要默默地失败boost::begin
and boost::end
没有明确定义,它会严重失败并出现错误
'type' : is not a member of 'boost::mpl::eval_if_c<C,F1,F2>'
[C=false, F1=boost::range_const_iterator<void *>, F2=boost::range_mutable_iterator<void *>]
在下面的代码中boost/range/iterator.hpp:63
:
typedef BOOST_RANGE_DEDUCED_TYPENAME
mpl::eval_if_c< is_const<C>::value,
range_const_iterator< typename remove_const<C>::type >,
range_mutable_iterator<C> >::type type;
(我有 boost 1.51,但 1.52 没有列出任何更改,1.53 alpha 列出了两个错误修复,但似乎都不相关)
那么有没有更好的方法来检测范围呢?虽然我一直在使用一些 C++03 编译器,并且可能会持续很长一段时间,但我想让它能够轻松切换到 C++11(其中免费)begin
and end
通过 ADL 提供似乎就足够了)。
具体来说,编译器是 Visual C++ 9.0 和 GCC 4.5。 SFINAE 对这两方面的支持都足够。