【问题标题】:Check for function signature also for inherited functions检查继承函数的函数签名
【发布时间】:2015-08-05 21:45:54
【问题描述】:

我需要检查容器擦除函数是否返回迭代器。我通常会通过例如检查函数签名促进。但是在 boost 类(例如 flat_set)的情况下,擦除是继承的,因此检查不会发现。但我真的需要它。 SFINAE to check for inherited member functions 只展示了一个我还不能使用的 C++11 解决方案。

我尝试过这样的事情:

    template <typename T> 
    class has_member_func_erase_it_constit
    { 
        typedef typename T::iterator iterator;
        typedef typename T::const_iterator const_iterator;
        typedef BOOST_TYPEOF_TPL(&T::erase) eraseType;

        typedef typename boost::function_types::result_type<eraseType>::type result;
    public: 
        static const bool value = boost::is_same<iterator, result>::value; 
    };

    template<class T>
    struct EraseReturnsIterator
    {
        static CONSTEXPR bool value = has_member_func_erase_it_constit<T>::value;
    };

但由于擦除过载而失败。我可能需要 decltype 或类似的东西来检查编译时使用 const_iterator 调用擦除的返回类型,但我找不到。

在 C++11 之前这怎么可能?

如果有一个擦除函数返回 void,这也不起作用:

    template <typename T> 
    class has_member_func_erase_it
    { 
        typedef typename T::iterator iterator;
        typedef typename T::const_iterator const_iterator;

        typedef char yes[1];
        typedef char no [2];

        static T makeT();
        static iterator makeIt();

        typedef BOOST_TYPEOF_TPL(makeT().erase(makeIt())) result;

    public: 
        static const bool value = boost::is_same<iterator, result>::value; 
    };

【问题讨论】:

  • 我怀疑你会更具体;一些容器有 > 1 个名为 erase 的方法。例如,vector 同时具有 erase(iterator)erase(iterator, iterator)
  • 在升级到 C++11 之前你会遇到多少个容器? 10?硬编码它们。 Ifdef C++11 做正确的事情,也许断言他们同意。
  • 我的意思是检查“无效擦除(迭代器)”与“迭代器擦除(迭代器)”。但我找到了一个可行的解决方案,并将在今天晚些时候发布。这是一个非常好的邪恶模板诡计。

标签: c++ boost traits template-meta-programming c++03


【解决方案1】:

以下作品:

    /// "Stores a type"
    template<typename T> struct Type2Type{
        typedef T type;
    };

    /// Evil hackery to put an expression into a type
    template<typename T>
    Type2Type<T> operator,(T, Type2Type<void>);

    template<typename T>
    T declval();

    template<class T>
    struct EraseReturnsIterator
    {
        typedef typename T::iterator iterator;
        typedef BOOST_TYPEOF_TPL((declval<T>().erase(declval<iterator>()), Type2Type<void>())) result;

        static CONSTEXPR bool value = boost::is_same<iterator, typename result::type>::value;
    };

基本上我们只是调用我们需要返回类型的函数。如果没有这种类型的函数返回 void,那么 BOOST_TYPEOF_TPL 就已经可以工作了。不幸的是,擦除 CAN 返回 void 会破坏实现,因为它试图将“void&”传递到堆栈的某处。

所以为了避免空洞(没有双关语),我们把它放在一个类型中,它包含一个类型。为了能够对表达式执行此操作,我们重载了逗号运算符。这种方式结果等于我们可以轻松阅读的“Type2Type”。完成!

逗号重载的想法:https://stackoverflow.com/a/5553460/1930508

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-22
    • 2021-07-19
    • 1970-01-01
    • 2018-12-08
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 2015-11-16
    相关资源
    最近更新 更多