Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 214
blahedo Avatar asked Dec 31 '25 08:12

blahedo


1 Answers

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. ]

like image 57
David G Avatar answered Jan 01 '26 20:01

David G



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!