2014-06-13 71 views
4

我有很多类暴露内部类型名为Binding。例如,其中一个可能是:如何推断C++中内部类型的外部类型?

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的方法吗?

显然,这纯粹是好奇心和美容问题。

+2

IIRC这是不可能的(类似于获取声明类型的名称空间)。但是你可以在'Binding'中提供一个typedef。而且,函数对象通常按值传递;依赖函数特征来获得operator()或类似的第一个参数的* single *参数类型是危险的,考虑重载'operator()'甚至C++ 1y的多态lambda表达式。 – dyp

+0

@dyp:为什么使用我的'FunctionTraits'来获取单个参数的类型是危险的? –

+0

第二种类型模板参数是多余的?编译器应该如何知道'BindingType'类型应该是什么类型,因此调用'TBindingExpression'时会调用什么重载? – rubenvb

回答

5
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<Message::Binding>Message

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

如果您愿意,您可以放弃帮手并重写outer_class_of_t=typename T::outer_class