【问题标题】:How can I deduce the outer type of an inner type in C++?如何在 C++ 中推断出内部类型的外部类型?
【发布时间】:2014-06-13 13:19:39
【问题描述】:

我有许多类公开了一个名为Binding 的内部类型。例如,其中之一可能是:

struct Message
{
    struct Binding
    {
    };
};

我像这样调用函数apply

apply< Message >([](Message::Binding& x)
{
    // setup binding fields
});

因为我写了

template <class TMessage, class TBindingExpression>
void apply(const TBindingExpression& expr)
{
    typedef typename TMessage::Binding BindingType;

    BindingType binding;
    expr(binding);

    apply(MessageUtil::typeId< TMessage >(), binding);
}

由于Message在我调用apply的方式上有点多余,我想让编译器推导出Message这样我就可以写了

apply([](Message::Binding x)
{
    //...
});

到目前为止,我被困在这里:

template <class TBindingExpression>
void apply(const TBindingExpression& expr)
{
    // I get the type of the argument which is Message::Binding in this example
    typedef typename std::tuple_element
    <
        0,
        FunctionTraits< TBindingExpression >::ArgumentTypes
    >
    ::type BindingType;

    // so I can invoke my expression
    BindingType binding;
    expr(binding);

    // But now I need the type of the outer class, i.e. Message
    typedef typename MessageTypeFromBinding< BindingType >::Type MessageType;

    apply(MessageUtil::typeId< MessageType >(), binding);
}

有没有办法写/实现MessageTypeFromBinding

显然,这纯粹是出于好奇和美观问题。

【问题讨论】:

  • IIRC 这是不可能的(类似于获取已声明类型的命名空间)。但是,您可以在 Binding 中提供 typedef。此外,函数对象通常按值传递。依赖函数特征来获取operator() 或类似的第一个参数的single 参数类型是危险的,考虑重载operator() 甚至C++1y 的多态lambda。
  • @dyp:为什么使用我的FunctionTraits 获取单个参数的类型很危险?
  • 第二种类型的模板参数如何冗余?编译器应该如何知道BindingType 应该是什么类型,以及调用TBindingExpression 时要调用什么重载?
  • @misterwhy 因为它只适用于一小部分可调用实体。
  • 在 c++14 中调用 apply&lt; Message &gt;([](auto&amp; x) { // setup binding fields }); 消除了冗余。

标签: c++ templates metaprogramming


【解决方案1】:
template<class T>struct inner_class_of{using outer_class=T;}; 

struct Message {
  struct Binding:inner_class_of<Message> {
  };
};

template<class T>
inner_class_of<T> get_outer_helper(inner_class_of<T>const&);

template<class T>
using outer_class_of_t = typename decltype(get_outer_helper(std::declval<T>()))::outer_class;

现在outer_class_of_t&lt;Message::Binding&gt;Message

我让它有点工业实力,因为即使 Binding 隐藏 outer_class 也能工作。

如果您愿意,可以删除助手并重写 outer_class_of_t=typename T::outer_class

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多