对于日志记录代码,我想检测是否可以使用Boost.Range中的工具对模板函数的给定参数进行迭代。显然我需要实例化不同的代码,所以我需要 SFINAE,可能(当然)结合 boost::enable_if。我试过检测是否定义begin
了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
,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
和通过 ADL 获得) end
.
具体来说,编译器是 Visual C++ 9.0 和 GCC 4.5。SFINAE 对两者的支持都足够了。