ADL и шаблоны
От: jazzer Россия Skype: enerjazzer
Дата: 23.01.08 07:25
Оценка: 15 (3)
Приветствую всех!

Вопрос такой: зачем в ADL включаются пространства типов, которыми инстанцированы шаблоны?
Я что-то не могу придумать ни одного разумного примера, только неразумные и вредные.

Вот пример, как это проявляется:
namespace x
{
  template <typename T>
  int distance( T b, T e );
  struct item {};  
}

namespace y
{
  template <typename T>
  int distance( T b, T e );
    
  template <typename T>
  struct i {};
  
  template <typename T>
  struct c
  {
    i<T> begin();
    i<T> end();
    int size() { return distance(begin(), end()); }
  };
}

void test()
{
  y::c<x::item>().size();
}

Комо ругается так:
"ComeauTest.c", line 23: error: more than one instance of function template
          "y::distance" matches the argument list, the choices that match are:
            function template "int y::distance(T, T)"
            function template "int x::distance(T, T)"
            The argument types that you used are: (y::i<x::item>, y::i<x::item>)
      int f() { return distance(begin(), end()); }
                       ^
          detected during instantiation of "int y::c<T>::f() [with T=x::item]"
                    at line 29


В моем случае это проявилось очень весело — был класс A, унаследованный от boost::mpl::empty_base в десятом поколении, и я создал std::list<A> — и не смог позвать size(), потому что в boost::mpl есть своя distance
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: ADL и шаблоны
От: Lorenzo_LAMAS  
Дата: 23.01.08 09:36
Оценка:
Не, ну мне кажется, что придумать случай, когда надо легко исходя буквально из твоих примеров:

namespace U
{
   template<class T>
   class i
   {
   /////
   };
}
namespace A
{
    class B{};
    void fun(const U::i<B> &);//хочу, чтобы ее нашли!!!
}

namespace U
{
   template<class T>
   class O
   {
   public:
       O(){i<T> a; fun(a);}
   };
}

int main()
{
    U::O<A::B> a;
}
Of course, the code must be complete enough to compile and link.
Re: ADL и шаблоны
От: zaufi Земля  
Дата: 23.01.08 09:44
Оценка:
вообще то тут нет ADL -- ADL работает по параметрам функций а не шаблонов...
ADL напримет тут:
namespace test 
{
    class T {};
    void f(T){};
}

test::T parm;

int main()
{
    f(parm); // OK: calls test::f
}
Re[2]: ADL и шаблоны
От: zaufi Земля  
Дата: 23.01.08 09:46
Оценка: :)
нет пожалуй я погорячился %)
Re[3]: ADL и шаблоны
От: Lorenzo_LAMAS  
Дата: 23.01.08 09:47
Оценка: :))
Здравствуйте, zaufi, Вы писали:


Z>нет пожалуй я погорячился %)

Я тоже успел погорячиться Но зато успел снести свой первый ответ
Of course, the code must be complete enough to compile and link.
Re[2]: ADL и шаблоны
От: jazzer Россия Skype: enerjazzer
Дата: 23.01.08 10:09
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Не, ну мне кажется, что придумать случай, когда надо легко исходя буквально из твоих примеров:


ты реалистичный пример приведи
таких-то я и сам нагереню сколько угодно
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: ADL и шаблоны
От: Lorenzo_LAMAS  
Дата: 23.01.08 10:47
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Lorenzo_LAMAS, Вы писали:


L_L>>Не, ну мне кажется, что придумать случай, когда надо легко исходя буквально из твоих примеров:


J>ты реалистичный пример приведи


А что для тебя реалистично? Если я дурацкие имена заменю именами из стандартной библиотеки, это сделает пример реалистичным или нет?
Of course, the code must be complete enough to compile and link.
Re[4]: ADL и шаблоны
От: jazzer Россия Skype: enerjazzer
Дата: 23.01.08 11:13
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Здравствуйте, jazzer, Вы писали:


J>>Здравствуйте, Lorenzo_LAMAS, Вы писали:


L_L>>>Не, ну мне кажется, что придумать случай, когда надо легко исходя буквально из твоих примеров:


J>>ты реалистичный пример приведи


L_L>А что для тебя реалистично? Если я дурацкие имена заменю именами из стандартной библиотеки, это сделает пример реалистичным или нет?


я имею в виду, чтоб эта фича решала какую-то более-менее реальную полезную задачу.

потому что в общем случае мы плодим кучу вложенных пространств имен для того, чтобы спрятать нечто и то, что с ним связано, а получается, что стоит проинстанцировать этим нечто какой-нть шаблон — и этот несчастный шаблон автоматически получает доступ ко всем потрохам, чего нам совершенно не нужно, нам бы как раз хотелось, чтоб такое происходило только по явному указанию.

Ведь идея какая — для внешнего мира шаблон класса не имеет связи с тем, чем его инстанцировали, если не предприняты специальные меры (например, шаблон наследуется от своего аргумента). Т.е. std::auto_ptr<int> и int — это совершенно несвязанные типы. И с какого перепугу вдруг везде, где я вызываю функции с std::auto_ptr<X::y>, должны дергаться еще и функции из совершенно левого пространства X — мне лично непонятно.

Причем обычно ты на это напарываться не будешь, потому что типы разные, но вот стоит завестись шаблонам, как в моем случае — и все, пиши пропало. А ведь, казалось бы, все спрятал во вложенных пространствах имен.

Т.е. унаследовался от чего-нть в boost или в std — и сразу получил из них в нагрузку кучу шаблонов к твоему ADL, безо всякого using namespace std.

Может быть, именно для защиты от этого boost::noncopyable сидит в своем пространстве:
namespace boost {
  namespace noncopyable_  // protection from unintended ADL
  {
    class noncopyable
    {
      ...
    };
  }
  typedef noncopyable_::noncopyable noncopyable;
}

правда, этот трюк у меня приводил к каким-то другим проблемам, уже не вспомню сейчас, к каким именно...
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: ADL и шаблоны
От: Lorenzo_LAMAS  
Дата: 23.01.08 12:04
Оценка: :))
J>потому что в общем случае мы плодим кучу вложенных пространств имен для того, чтобы спрятать нечто и то, что с ним связано, а получается, что стоит проинстанцировать этим нечто какой-нть шаблон — и этот несчастный шаблон автоматически получает доступ ко всем потрохам, чего нам совершенно не нужно, нам бы как раз хотелось, чтоб такое происходило только по явному указанию.

J>Ведь идея какая — для внешнего мира шаблон класса не имеет связи с тем, чем его инстанцировали, если не предприняты специальные меры (например, шаблон наследуется от своего аргумента). Т.е. std::auto_ptr<int> и int — это совершенно несвязанные типы. И с какого перепугу вдруг везде, где я вызываю функции с std::auto_ptr<X::y>, должны дергаться еще и функции из совершенно левого пространства X — мне лично непонятно.


J>Причем обычно ты на это напарываться не будешь, потому что типы разные, но вот стоит завестись шаблонам, как в моем случае — и все, пиши пропало. А ведь, казалось бы, все спрятал во вложенных пространствах имен.


Наверное, люди придумавшие АДЛ на это сказали бы "ну, мы вообще-то хотели как лучше, а получилось .... как всегда"
Of course, the code must be complete enough to compile and link.
Re: ADL и шаблоны
От: s.ts  
Дата: 23.01.08 15:19
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Приветствую всех!


J>Вопрос такой: зачем в ADL включаются пространства типов, которыми инстанцированы шаблоны?

J>Я что-то не могу придумать ни одного разумного примера, только неразумные и вредные.

namespace my
{
  struct My {};
  ostream& operator << (ostream&, const My &)
  {
  ...
  }
}
...
my::My m;
std::cout << m;
Re: ADL и шаблоны
От: NotImplemented США github.com/NotImplemented
Дата: 23.01.08 15:30
Оценка: 20 (2)
Здравствуйте, jazzer, Вы писали:

J>Приветствую всех!


J>Вопрос такой: зачем в ADL включаются пространства типов, которыми инстанцированы шаблоны?


Предложение Саттера о внесении изменений в ADL:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2103.pdf

Пример оттуда:
#include <vector>
namespace N 
{
  struct X { };
  template<typename T>
  int* operator+( T , unsigned )
  { 
    static int i ; return &i ; /* just to stub in the function body */ 
  }
}
  
int main() 
{
  std::vector< N::X > v(5);
  v[ 0 ];
}

// An extract from libstdc++ 3.2, distilled and edited
namespace __gnu_cxx 
{
  template<typename T> class __normal_iterator 
  {
    public:
    __normal_iterator operator+(const long& __n) const {…}
  };
}

namespace std 
{
  template <class T> class vector 
  {
  public:
    typedef __gnu_cxx::__normal_iterator<T> iterator;
    iterator operator[](unsigned __n) { return iterator() + __n; }
  };
}

In this case, we might argue that this is a problem with ADL. Under the current rules N is an associated
namespace of __normal_iterator<N::X>, so N::operator+<N::X>( unsigned ) should be considered,
and it happens to be a better match. Yes, the library implementer could have written the code
more defensively.
But what about a library that is written to avoid ADL? From Dinkumware 3.13:


//An extract from Dinkumware 3.13, distilled and edited
namespace std 
{
  template<class T> struct _Ranit { };
  template<class T> class vector 
  {
  public:
    class iterator : public _Ranit<T> 
    {
    public:
      iterator operator+(int) const { return iterator(); }
    };
  iterator operator[](unsigned _Pos) { return iterator()+_Pos; }
  };
}

Compiling this code under various compilers produces various results. This is a case of “Compiler
Bugs Bite,” because N is not an associated namespace of std::vector<N::X>::iterator (the _Ranit<T>
base doesn’t matter). But all shipping versions I tried of Gnu g++ (up to 3.4.3) and Microsoft VC++ (up
to 7.1) do incorrectly find it. Comeau 4.3.3 and the current beta of Microsoft VC++ 8 are two compilers
that correctly do not find it.
Re: ADL и шаблоны
От: jazzer Россия Skype: enerjazzer
Дата: 25.01.08 03:32
Оценка:
Здравствуйте, jazzer, Вы писали:

J>В моем случае это проявилось очень весело — был класс A, унаследованный от boost::mpl::empty_base в десятом поколении, и я создал std::list<A> — и не смог позвать size(), потому что в boost::mpl есть своя distance


В общем, поскольку мой случай был связан с STL, я закинул баг репорт в STLport (основываясь на 17.4.1.1/3), вроде, они согласились его фиксить.

17.4.1.1/3
Whenever a name x defined in the standard library is mentioned, the name x is assumed to be fully qualified as ::std::x, unless explicitly described otherwise. For example, if the Effects section for library function F is described as calling library function G, the function ::std::G is meant.


Так что будем подождать.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.