2017-06-13 96 views
4

下面的代碼編譯工作,但將無法正常工作:C++模板特不嵌套類型

template<typename T> 
struct Nesting 
{ 
    template<typename U> 
    struct _Nested 
    { 
    }; 

    template<typename U> 
    using Nested = _Nested<U>; 
}; 

template<typename T> 
struct F 
{ 
    static constexpr bool is_my_nested_class = false; 
}; 

template<typename T, typename U> 
struct F<typename Nesting<T>::Nested<U>> 
{ 
    static constexpr bool is_my_nested_class = true; 
}; 

我創建這些嵌套和嵌套類型,並嘗試在其上使用類型特徵的圖案。它編譯(使用MSVC2014瓦特/ CPP11),但

F<Nesting<int>::Nested<long>>::is_my_nested_class 

回報

這是標準禁止或未定義的嗎?它打破了什麼規則?任何解決方法?

非常感謝!

+5

我相當確信結構F中的T'嵌套嵌套 ::嵌套>處於不可僞裝的上下文中,因爲這樣的編譯器在傳入類型時無法建立'T'和'U'模板實例化 –

+5

'struct F ::嵌套>'我應該認爲'struct F :: template嵌套>'。然後,叮噹聲4.0給出:'錯誤:類模板部分特化包含無法推斷的模板參數;這部分專業化將永遠不會被使用' – davmac

+0

感謝您的幫助,我修改了F,以便給出參數T而不是被推導出來(不能)。沒有類型別名,它告訴我U不能被推斷出來。如果我將兩個參數都提供給F(不是推導出來的),它可以正常工作。非常感謝你,我想我明白了這個問題:)我也覺得有趣的事實是,如果嵌套是非模板類型,那麼推導出U.可能有一些基本概念我還沒有把握,在這裏! – Michel

回答

1

你嵌套別名可以指任何類型的,尤其是在專業化:

template<typename T> 
struct Nesting 
{ 
    template<typename U> 
    struct _Nested 
    { 
    }; 

    template<typename U> 
    using Nested = _Nested<U>; 
}; 

// Consider this specialisation: 
template<> 
struct Nesting<int> 
{ 
    template<typename U> 
    using Nested = float; 
}; 

現在,顯然F<Nesting<int>::Nested<int>>::is_my_nested_class應該是一樣的F<float>::is_my_nested_class,然而,如何才能編譯器推斷這對於後一種情況?也就是說,如果我寫的:

static_assert(F<float>::is_my_nested_class, "not nested"); 

,編譯器將需要看到的是F<float>相同F<Nesting<int>::Nested<int>>,即使後者尚未實例。由於無法合理預期這樣做,因此不允許此案。

+0

非常感謝你的回答! 我的問題可能是我不知道編譯器如何推導簡單的F :: is_my_nested_class大小寫的類型。 在模板類型推演之後解決了類型別名問題嗎? 它會工作,如果我擺脫了類型別名? – Michel

+0

您的評論是非常有幫助的!謝謝! (所以,不,它不會解決任何問題,以擺脫類型別名:)) – Michel

+0

@Michel,對,如果你擺脫了類型別名,它並沒有幫助,因爲外部模板的專門化可能會重新引入反正類型別名。實質上,實際問題是內部類型的標識依賴於外部類型,這可以是專用的。 – davmac