How to make C++ find templated function header when dependent-scoped inner classes are involved?

和自甴很熟 提交于 2019-12-23 18:57:06

问题


I'm trying to build a templated C++ function that accepts, as its argument, a pointer to an object of an inner class. Here is a reduced version of the class structure involved, similar to a typical linked-list or tree class:

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

  Inner* ptr;

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

I've made them structs to exclude any access control issues and removed some extraneous instance variables. With that class structure in mind, here are three functions, the first two of which aren't quite what I want:

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

This third function is basically what I want, header-wise (it's intended as a helper function in a larger body of code, of course), but it doesn't work. If I compile and run the following main function:

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

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

it runs just fine (printing 5 three times), but if I uncomment the line with the call to testInnerTemplated, I get a compiler error saying no matching function for call to ‘testInnerTemplated(Outer<int>::Inner*&)’ (in g++ 4.9.1). I guess it's a problem with the template lookup or matching, but how can I tell the compiler how to resolve it?


回答1:


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

The compiler can't deduce T through template argument deduction because this is a non-deduced context as defined in the standard:

The nondeduced contexts are:

The nested-name-specifier of a type that was specified using a qualified-id. A type that is a template-id in which one or more of the template-arguments is an expression that references a template-parameter.

When a type name is specified in a way that includes a nondeduced context, all of the types that comprise that type name are also nondeduced. However, a compound type can include both deduced and nondeduced types. [Example: If a type is specified as A<T>::B<T2>, both T and T2 are nondeduced. Likewise, if a type is specified as A<I+J>::X<T>, I, J, and T are nondeduced. If a type is specified as void f(typename A<T>::B, A<T>), the T in A<T>::B is nondeduced but the T in A<T> is deduced. ]




回答2:


If you wish to recover the type information from Outer<> from within Inner, you can use traits.

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)) {}
};

Now define a more generic testInnerTemplated, but it uses traits to recover the type information passed to Outer<>.

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


来源:https://stackoverflow.com/questions/24942729/how-to-make-c-find-templated-function-header-when-dependent-scoped-inner-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!