gpt4 book ai didi

c++ - 使用 SFINAE 检测某物是否在( boost )范围内

转载 作者:太空狗 更新时间:2023-10-29 20:43:50 26 4
gpt4 key购买 nike

对于日志记录代码,我想检测是否可以使用 Boost.Range 中的工具迭代模板函数的给定参数。或不。显然我需要实例化不同的代码,无论是否,所以我需要 SFINAE,可能(好吧,当然)结合 boost::enable_if。我尝试检测是否定义了 beginend 自由函数,如下所示:

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::beginboost::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(免费 beginend 通过 ADL 可用似乎是所需要的全部)。

具体来说,编译器是 Visual C++ 9.0 和 GCC 4.5。 SFINAE 对两者的支持都足够。

最佳答案

我相信您需要使用的元函数是 has_range_iterator .

Running on LWS

#include <iostream>
#include <string>
#include <utility>

#include <boost/range.hpp>

template <typename T>
typename boost::disable_if<boost::has_range_iterator<T> >::type repr(const T &, const std::string& name)
{ std::cout << name << " is not a range" << std::endl; }

template <typename T>
typename boost::enable_if<boost::has_range_iterator<T> >::type repr(const T &, const std::string& name)
{ std::cout << name << " is a range" << std::endl; }

struct foo{};
struct bar
{
typedef int iterator;
typedef const int const_iterator;
int begin(){ return 0;};
int end(){ return 1;};
};


int main()
{
int i;
repr(i, "int");
int array[10];
repr(array, "int array");
std::string str;
repr(str, "std::string");
foo f;
repr(f, "foo");
bar b;
repr(b, "bar");

std::pair<int, int> p;
repr(p, "pair"); // it does make a mistake here, because std::pair<int, int> looks like range, but int is not valid iterator (cannot be dereferenced)
}

关于c++ - 使用 SFINAE 检测某物是否在( boost )范围内,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14439479/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com