嵌套说明符中使用的模板不完整类型
template incomplete type used in nested specifier
我已经查看了几个切合主题的问题,但没有帮助,抱歉,如果重复了。
为什么 Inner
是一个不完整的类型?循环依赖在哪里?
P.S。 NOT_USED
是一个占位符 class 以保持部分专业化
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
}
更新
如果我将第二专业更改为 (NOT_USED->Type
, is_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
模板参数的依赖以某种方式改变了实例化过程?
Clang 错误消息更明确:
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...
由于您有一个 enable_if
将实例化限制为 A == int,因此您无法实例化 Outer<double>::Inner<void>
。
可能的修复:
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"; } };
};
我已经查看了几个切合主题的问题,但没有帮助,抱歉,如果重复了。
为什么 Inner
是一个不完整的类型?循环依赖在哪里?
P.S。 NOT_USED
是一个占位符 class 以保持部分专业化
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
}
更新
如果我将第二专业更改为 (NOT_USED->Type
, is_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
模板参数的依赖以某种方式改变了实例化过程?
Clang 错误消息更明确:
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...
由于您有一个 enable_if
将实例化限制为 A == int,因此您无法实例化 Outer<double>::Inner<void>
。
可能的修复:
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"; } };
};