2017-04-07 72 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