ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – 使用SFINAE检测是否有(增强)范围

2019-09-01 09:17:28  阅读:227  来源: 互联网

标签:c boost sfinae c03


对于日志代码,我想检测模板函数的给定参数是否可以使用Boost.Range中的工具进行迭代.显然我需要实例化不同的代码,不管是不是,所以我需要SFINAE,可能(当然)与boost :: enable_if结合使用.我试过检测是否定义了开始和结束自由函数,如下所示:

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;

(我有1.51提升,但1.52列出没有变化,1.53 alpha列出两个错误修复,但似乎都没有相关)

那么有更好的方法来检测范围吗?虽然我遇到了一些C 03编译器并且可能会持续很长一段时间,但我希望能够轻松切换到C 11(通过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,boost,sfinae,c03
来源: https://codeday.me/bug/20190901/1782414.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有