【问题标题】:determine if struct has a member of specific type确定结构是否具有特定类型的成员
【发布时间】:2015-09-25 22:18:34
【问题描述】:

假设我有一个结构 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>);
}

我所要求的似乎很可能是不可能的。我找不到副本,但我很惊讶我找不到,所以它可能就在那里。

【问题讨论】:

  • 这是不可能的,C++ 没有反射。但是,对于 std::tuple 之类的东西,它非常简单。
  • 基本上,您需要反思。 C++ 不做反射。但我不禁想知道:假设您以某种方式设法实现has_int - 您打算如何使用它?您要解决的真正问题是什么?
  • @IgorTandetnik 我处于需要小心处理包含指针或引用的结构的情况。关键是要决定在编译时允许哪些操作。我真的无法详细解释。
  • 我对内置的一无所知。您在运行时不需要这个,所以您是否考虑过使用第三个程序来解析文件并生成将与您的程序的其余部分一起编译的适当源代码?
  • 在我们有可用的静态反射提案之前,请检查:reddit.com/r/cpp/comments/3lh8me/…

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


【解决方案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 序列时才有效。对您而言,这意味着您想在编译时以这种方式推理的任何类型,您都需要使用宏来定义或调整。如果您正在编写一个旨在为任意库用户定义类型工作的库,这可能是您无法接受的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 2019-12-31
    • 2011-04-15
    • 2017-06-23
    • 2020-07-08
    • 2020-03-29
    相关资源
    最近更新 更多