当涉及依赖范围的内部类时,如何使C ++找到模板化的函数头?

时间:2014-07-24 19:49:29

标签: c++ templates inner-classes

我正在尝试构建一个模板化的C ++函数,该函数接受一个指向内部类对象的指针作为其参数。这是所涉及的类结构的简化版本,类似于典型的链表或树类:

template <typename T>
struct Outer
{
  struct Inner
  {
    T val;
    Inner (T v) : val(v) { }
  };

  Inner* ptr;

  Outer(T val)
  {
    ptr = new Inner(val);
  }
};

我已经使它们成为排除任何访问控制问题的结构,并删除了一些无关的实例变量。考虑到这个类结构,这里有三个函数,前两个函数不是我想要的:

template <typename T>
void testOuter (const Outer<T>& obj)
{
  cout << obj.ptr->val << endl;
}

void testInnerInt (const Outer<int>::Inner* p)
{
  cout << p->val << endl;
}

template <typename T>
void testInnerTemplated (const typename Outer<T>::Inner* p)
{
  cout << p->val << endl;
}

这第三个函数基本上就是我想要的,标题(它当然是作为一个更大的代码体中的辅助函数),但它不起作用。如果我编译并运行以下主函数:

int main()
{
  Outer<int> foo(5);

  cout << foo.ptr->val << endl;
  testInnerInt(foo.ptr);
  //testInnerTemplated(foo.ptr);
  testOuter(foo);
}

它运行得很好(打印5三次),但如果我通过调用testInnerTemplated取消注释该行,我会收到编译错误no matching function for call to ‘testInnerTemplated(Outer<int>::Inner*&)’(以g ++ 4.9为单位)。 1)。我想这是模板查找或匹配的问题,但我怎么能告诉编译器如何解决它?

2 个答案:

答案 0 :(得分:1)

template <typename T>
void testInnerTemplated(const typename Outer<T>::Inner*);

编译器无法通过模板参数推导推导T,因为这是标准中定义的非推导上下文:

  

非弱势语境是:

     

使用qualified-id指定的类型的嵌套名称说明符。一种类型,它是一个template-id,其中一个或多个template-arguments是一个引用模板参数的表达式。

     

如果以包含非弱化上下文的方式指定类型名称,则包含该类型名称的所有类型也不会受到限制。但是,复合类型可以包括推导类型和非推导类型。 [示例:如果类型指定为A<T>::B<T2>,则TT2都不受限制。同样,如果某个类型指定为A<I+J>::X<T>,则IJT不会被限制。如果将类型指定为void f(typename A<T>::B, A<T>),则T中的A<T>::B未受到限制,但推导出T中的A<T>。 ]

答案 1 :(得分:1)

如果您希望从Outer<>内的Inner恢复类型信息,则可以使用特征。

template <typename T>
struct Outer
{
    typedef T TypeParam;

    struct Inner
    {
        typedef Outer<T> InnerOuter;
        T val;
        Inner (T v) : val(v) {}
    };

    Inner *ptr;

    Outer (T val) : ptr(new Inner(val)) {}
};

现在定义更通用的testInnerTemplated,但它使用特征来恢复传递给Outer<>的类型信息。

template <typename T>
void testInnerTemplated (const T * p)
{
  typename T::InnerOuter::TypeParam val = p->val;
  std::cout << val << std::endl;
}