确定struct是否具有特定类型的成员

时间:2015-09-25 22:18:34

标签: c++ templates c++11 template-meta-programming sfinae

我们说我有一个结构Foo,我想确定Foo内部是否有int

struct Foo { int a; char c; };
has_int<Foo>::value; // should be true

这是我实际想要的最基本形式,检查特定类型:

has_type<Foo, int>::value;

如果我知道如何做到这一点,我可以将其转化为我的最终目标:

has_pointer<Foo>::value; // false
struct Bar { int a; void *b; };
has_pointer<Bar>::value; // true

至于我尝试过的事情,很难开始,我能想到的最好的事情是,如果我能得到一个结构中包含的类型的包,我可以写其余的:

template <typename... Ts>
constexpr bool any_is_pointer() noexcept {
    return (... || std::is_pointer_v<Ts>);
}

我要求的似乎很可能是不可能的。我找不到副本,但我很惊讶我不能这样做。

1 个答案:

答案 0 :(得分:1)

正如其他人所说,你想要的东西现在不可能用任意类型的vanilla C ++。但是,如果您能够提供某些编译时信息以及您需要在其定义中操作的类型,那么您可以执行您要执行的操作。

您可以使用boost fusion库的适配器来实现这一点,它允许您调整现有结构以成为融合容器或定义为融合容器建模的新结构。然后,您可以使用任何您想要执行编译时检查类型的boost :: mpl算法。

考虑这个示例,使用您的struct foo和您想要的has_type编译时算法:

#include <boost/fusion/adapted/struct/define_struct.hpp>
#include <boost/mpl/contains.hpp>

BOOST_FUSION_DEFINE_STRUCT(
    (your_namespace), foo, 
    (int, a) 
    (char, c))

template<typename source_type, typename search_type>
struct has_type
{
    typedef typename boost::mpl::contains<source_type, search_type>::type value_type;
    static const bool value = value_type::value;
};

#include <iostream>

int main()
{
    bool foo_has_int_pointer = has_type<your_namespace::foo, int*>::value;
    bool foo_has_int = has_type<your_namespace::foo, int>::value;

    std::cout << "foo_has_int_pointer: " << foo_has_int_pointer << "\n";
    std::cout << "foo_has_int: " << foo_has_int << "\n";

    your_namespace::foo my_foo;

    my_foo.a = 10;
    my_foo.c = 'x';

    std::cout << "my_foo: " << my_foo.a << ", " << my_foo.c;
}

查看输出或混乱示例:http://ideone.com/f0Zc2M

如您所见,您使用BOOST_FUSION_DEFINE_STRUCT宏来定义您希望在编译时操作的struct成员。 fusion提供了几个其他宏来定义这样的结构,以及用于适应已定义结构的宏。检查出here

当然,你可能已经可以在这里告诉我们。 has_type仅在source_type是boost :: mpl / boost :: fusion序列时才有效。对于您来说,这意味着您希望以这种方式在编译时推理出任何类型,您需要使用宏来定义或调整。如果您正在编写一个适用于任意库用户定义类型的库,那么您可能无法接受。