检查类型是否具有Boost TTI的成员函数(也包括固有成员函数)

Check if a type has a member function (inhrited member functions also) with Boost TTI

本文关键字:成员 函数 包括固 TTI 是否 类型 Boost 检查      更新时间:2023-10-16

Boost TTI具有非常方便的宏,用于检查类型是否具有成员函数。请参见此处。

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

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

正如库的创建者Edward Diener在这个线程中告诉我们的那样:

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;
}

情况(2(是一个错误,因为返回int的名为function1的函数是在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_...结构,后者将进行检查。没有添加算法,只是使用存在量化来提升谓词的机制:

如果层次结构中任何一个上升的类都有这样的成员函数,则返回真正的

有了这个工具,在你的情况下,你可以写

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

模板参数为:

  1. 检查成员函数的结构(例如has_member_function_function2(
  2. 函数的返回类型
  3. 层次结构中任意数量的类

2.自动生成基类

上述解决方法的缺点是必须手动提供基类在练习通用编程时,过于具体是一个缺点

进行这种内省的一种方法是通过std::tr2::bases。如果你有一个支持它的实现(它将在一段时间内成为标准(,你终于可以使用TTI:进行内省了

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

HTH