This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115c. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-09-25


321. Associated classes and namespaces for argument-dependent lookup

Section: 6.5.4  [basic.lookup.argdep]     Status: dup     Submitter: Andrei Iltchenko     Date: 12 Nov 2001

The last bullet of the second paragraph of section 6.5.4 [basic.lookup.argdep] says that:

If T is a template-id, its associated namespaces and classes are the namespace in which the template is defined; for member templates, the member template's class; the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters); the namespaces in which any template template arguments are defined; and the classes in which any member templates used as template template arguments are defined.

The first problem with this wording is that it is misleading, since one cannot get such a function argument whose type would be a template-id. The bullet should be speaking about template specializations instead.

The second problem is owing to the use of the word "defined" in the phrases "are the namespace in which the template is defined", "in which any template template arguments are defined", and "as template template arguments are defined". The bullet should use the word "declared" instead, since scenarios like the one below are possible:

namespace  A  {

   template<class T>
   struct  test  {

      template<class U>
      struct  mem_templ  {   };

   };

   // declaration in namespace 'A'
   template<> template<>
   struct  test<int>::mem_templ<int>;

   void  foo(test<int>::mem_templ<int>&)
   {   }

}

// definition in the global namespace
template<> template<>
struct  A::test<int>::mem_templ<int>  {
};

int  main()
{
   A::test<int>::mem_templ<int>   inst;
   // According to the current definition of 3.4.2
   // foo is not found.
   foo(inst);
}

In addition, the bullet doesn't make it clear whether a T which is a class template specialization must also be treated as a class type, i.e. if the contents of the second bullet of the second paragraph of section 6.5.4 [basic.lookup.argdep].

must apply to it or not. The same stands for a T which is a function template specialization. This detail can make a difference in an example such as the one below:
template<class T>
struct  slist_iterator  {
   friend bool  operator==(const slist_iterator& x, const slist_iterator& y)
   {   return  true;   }
};

template<class T>
struct  slist  {
   typedef slist_iterator<T>   iterator;
   iterator  begin()
   {   return  iterator();   }
   iterator  end()
   {   return  iterator();   }
};

int  main()
{
   slist<int>   my_list;
   slist<int>::iterator   mi1 = my_list.begin(),  mi2 = my_list.end();
   // Must the the friend function declaration
   // bool  operator==(const slist_iterator<int>&, const slist_iterator<int>&);
   // be found through argument dependent lookup? I.e. is the specialization
   // 'slist<int>' the associated class of the arguments 'mi1' and 'mi2'. If we
   // apply only the contents of the last bullet of 3.4.2/2, then the type
   // 'slist_iterator<int>' has no associated classes and the friend declaration
   // is not found.
   mi1 == mi2;
}

Suggested resolution:

Replace the last bullet of the second paragraph of section 6.5.4 [basic.lookup.argdep]

with

Replace the second bullet of the second paragraph of section 6.5.4 [basic.lookup.argdep]

with

Rationale (September, 2012):

The concerns in this issue were addressed by the resolutions of issues 403 and 557.