嵌套说明符

时间:2017-04-07 14:34:25

标签: c++ templates sfinae

我已经查看了几个主题问题,但它没有帮助,抱歉,如果重复的话。

为什么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
}

更新

如果我将第二个专精更改为(NOT_USED->Typeis_same<int, A> - &gt; 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> - &gt; Inner<T>

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

一切都在编译。这是为什么?显然,对Outer模板参数的依赖会以某种方式改变实例化过程吗?

2 个答案:

答案 0 :(得分:1)

可能的解决办法:

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"; } };
};

答案 1 :(得分:0)

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>