使用Boost TTI检查类型是否具有成员函数(也是已注册的成员函数)

时间:2014-05-04 22:00:19

标签: c++ boost typetraits

Boost TTI具有非常方便的宏,用于检查类型是否具有成员函数。 See here

但是BOOST_TTI_HAS_MEMBER_FUNCTION对于继承的成员函数返回false。有一个方便的Boost解决方案吗?

我知道自定义SFINAE solution的现有线程。但我更喜欢Boost解决方案,因为我更确定它适用于更多的编译器,我希望避免为每个这样的特定行为维护代码。我也在使用Boost类似的库。

1 个答案:

答案 0 :(得分:3)

正如图书馆的创建者爱德华·迪纳(Edward Diener)在this thread中通知我们:

  

TTI无法识别继承的成员函数,即使它们是公共的。

因此,既然你仍然想要使用TTI,那就让我们来解决。我将使用类似于BOOST中相关手册页的示例,只会将继承添加到“问题”中。 :

struct AClass { };

struct Top {
    int function1();
    AClass function2(double, short *);
};

struct Top2 : Top {
    long function2(Top &, int, bool, short, float);
    Top * function3(long, int, AClass &);
};

int main()
{
    cout << has_member_function_function1<Top, int>::value << endl;; // 1. true
    cout << has_member_function_function1<Top2, int>::value << endl; // 2. false
    return 0;
}

Case(2)是一个错误,因为返回function1的名为int的函数在Top2,类Top

的基类中定义

1。跨类层次结构检查的机制

第一步是建立一个将 TTI检查应用于任意数量的类的机制:

template <
    template <class, class, class, class> class check,
    typename Ret, typename... Bases
>
struct has_m_f;


template < 
    template <class, class, class, class> class check, 
    typename Ret, typename Base
>
struct has_m_f <check, Ret, Base>
{
    static const bool value = check<Base, Ret, 
        boost::mpl::vector<>, boost::function_types::null_tag>::value;
};


template < 
    template <class, class, class, class> class check, 
    typename Ret, typename Base, typename... Bases
>
struct has_m_f <check, Ret, Base, Bases...>
{
    static const bool value = check<Base, Ret, 
        boost::mpl::vector<>, boost::function_types::null_tag>::value 
        || has_m_f<check, Ret, Bases...>::value;
};

has_m_f是一个结构,它将任意长度的类转发到has_member_function_...结构,这将进行检查。没有添加算法,只是一种使用存在量化来提升谓词的机制:

  

如果任何升级层次结构的类具有这样的成员函数,则返回true

使用此工具,在您的情况下,您可以写

has_m_f < has_member_function_function1, int, Top2, Top >::value;

模板参数是:

  1. 检查成员函数的结构(例如has_member_function_function2
  2. 功能的返回类型
  3. 层次结构中任意数量的类
  4. 2。自动生成基类

    上述解决方法的缺点是您必须手动提供基类。 在练习泛型编程时,具体是一个缺点

    进行这种反省的方法是std::tr2::bases。如果你有一个支持它的实现(它将成为#34;而#34;)你可以最终使用TTI进行内省:

    has_m_f < has_member_function_function1, int, Top2,
                std::tr2::bases<Top2>::type >::value;
    

    HTH