2017-04-07 70 views
1

我已經瀏覽了幾個主題上的問題,但它沒有幫助,如果重複則很抱歉。嵌套說明符中使用的模板不完整類型

爲什麼Inner是不完整的類型?循環依賴在哪裏?

P.S. NOT_USED是一個佔位符類,以保持專業化部分

template <class A> 
struct Outer 
{ 
    template <class NOT_USED, class Enabled = void> 
    struct Inner 
    { static void inner() { std::cout << "not enabled\n"; } }; 

    template <class NOT_USED> 
    struct Inner<NOT_USED, typename std::enable_if<std::is_same<int, A>::value>::type> 
    { static void inner() { std::cout << "enabled\n"; } }; 
}; 

template <class A> 
void call_inner(A& a) 
{ 
    Outer<A>::template Inner<void>::inner(); // #1 
} 

int main() 
{ 
    int intVar = 10; 
    double doubleVar = 1; 
    call_inner(intVar); // OK 
    call_inner(doubleVar); // Error at #1: incomplete type ‘Outer<double>::Inner<void>’ used in nested name specifier 
} 

UPDATE

如果我更改第二個專業化(NOT_USED->Typeis_same<int, A> - >is_same<int, Type>

template<typename Type> 
struct Inner<Type, typename std::enable_if<std::is_same<int, Type>::value>::type> 
{ static void inner() { std::cout << "enabled\n"; } }; 

而且call_inner來(注Inner<void>Inner<T>

template <class T> 
void call_inner(T& t) 
{ 
    Outer<T>::template Inner<T>::inner(); 
} 

全部彙編。這是爲什麼?顯然,依靠Outer模板參數會以某種方式改變實例化過程?

回答

0

鐺錯誤消息更加明確:

ess.cpp:11:52: error: no type named 'type' in 
     'std::__1::enable_if<false, void>'; 'enable_if' cannot be used to disable 
     this declaration 
    ...Inner<NOT_USED, typename std::enable_if<std::is_same<int, A>::value>::type> 
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 
ess.cpp:18:5: note: in instantiation of template class 'Outer<double>' requested 
     here 
    Outer<A>::template Inner<void>::inner(); // #1 
    ^
ess.cpp:26:5: note: in instantiation of function template specialization 
     'call_inner<double>' requested here 
    call_inner(doubleVar); // Error at #1: incomplete type <BF>Outer<dou... 

當你有一個限制instanciation到A == INT的enable_if,你不能實例Outer<double>::Inner<void>

+0

爲什麼SFINAE在這裏不適用?請看最新的問題,'Inner'實例化有什麼區別? – DimG

0

一個可能的解決辦法:

template <class A> 
struct Outer 
{ 
    template <class NOT_USED, typename T = A, class Enabled = void> 
    struct Inner 
    { static void inner() { std::cout << "not enabled\n"; } }; 

    template <class NOT_USED, typename T> 
    struct Inner<NOT_USED, T, 
       typename std::enable_if<std::is_same<int, T>::value 
             && std::is_same<A, T>::value>::type> 
    { static void inner() { std::cout << "enabled\n"; } }; 
}; 
+0

你能否詳細說明如何以及爲什麼依賴'Outer'模板參數改變'內部'實例化行爲? – DimG

+1

'std :: is_same '不依賴於'Inner',而'std :: is_same '是。所以在一種情況下你有硬錯誤失敗,而在另一種情況下你有替代失敗(和SF INAE :))。 – Jarod42