2014-06-13 67 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