Проблема с Dependent Name Lookup
От: Антибиотик Россия  
Дата: 29.09.09 08:54
Оценка: 29 (1)
имеется следующий код:
#include <iostream>
using namespace std;

namespace A {
     template <typename T>
     void foo(T*)
     {
       cout << "void foo(T*)\n";
     }
};

class B {
public:

     friend void A::foo<>(B*);
private:
     int b_;
};

int main()
{
  B b;
  foo(&b);

  return 0;
}

который нормально компилируется, но почему-то не работает так, как ожидается. Точнее, функция foo фактически не вызывается.
Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?
visual studio .net
Re: Проблема с Dependent Name Lookup
От: The_Thing Россия
Дата: 29.09.09 09:07
Оценка:
Здравствуйте, Антибиотик, Вы писали:
1. не компилируется, так как foo не найдена, надо A::foo — так всё работает.
2. не понял при чём тут B.

А>имеется следующий код:

А>
1
А>#include <iostream>
А>using namespace std;

А>namespace A {
А>     template <typename T>
А>     void foo(T*)
А>     {
А>       cout << "void foo(T*)\n";
А>     }
А>};

А>class B {
А>public:

А>     friend void A::foo<>(B*);
А>private:
А>     int b_;
А>};

А>int main()
А>{
А>  B b;
А>  foo(&b);

А>  return 0;
А>}

А>

А>который нормально компилируется, но почему-то не работает так, как ожидается. Точнее, функция foo фактически не вызывается.
А>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?
Re: Проблема с Dependent Name Lookup
От: Кодт Россия  
Дата: 29.09.09 09:13
Оценка: +1
Здравствуйте, Антибиотик, Вы писали:

А>имеется следующий код:

А>который нормально компилируется,

VC2005 (другими не пробовал), но не gcc и не comeau.

G++ 3.4.4, например:
t.cpp:15: error: `void A::foo(B*)' should have been declared inside `A'
t.cpp: In function `int main()':
t.cpp:23: error: `foo' undeclared (first use this function)
t.cpp:23: error: (Each undeclared identifier is reported only once for each function it appears in.)


А> но почему-то не работает так, как ожидается. Точнее, функция foo фактически не вызывается.


Баг VC.
Попросту не сгенерировал никакой код.

А>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?


Кстати, обычно это называют ADL (argument dependent lookup), без ...name... — если захочешь в гугле искать, чтоб проблем не было.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re: Проблема с Dependent Name Lookup
От: jazzer Россия Skype: enerjazzer
Дата: 29.09.09 09:14
Оценка:
Здравствуйте, Антибиотик, Вы писали:

А>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?


1) Синтаксис объявления друга неправильный, должно быть:
     template<typename T> friend void A::foo(B*);


2) GCC 3.4.6 компилирует и всё работает

Что за компилятор?
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[2]: Проблема с Dependent Name Lookup
От: Антибиотик Россия  
Дата: 29.09.09 09:17
Оценка:
Здравствуйте, The_Thing, Вы писали:

T_T>Здравствуйте, Антибиотик, Вы писали:

T_T>1. не компилируется, так как foo не найдена, надо A::foo — так всё работает.
T_T>2. не понял при чём тут B.

1. используется компилятор Microsoft Visual C++ 2008 Express, в нем все нормально компилируется
2. это упрощенный пример более сложного кода, суть в том, что функция foo вызывается с аргументом типа B. Чтобы было понятнее, пусть функция foo выглядит так:
template <typename T>
     void foo(T* t)
     {
       cout << t->b_;
     }
Re[2]: Проблема с Dependent Name Lookup
От: Кодт Россия  
Дата: 29.09.09 09:19
Оценка:
Здравствуйте, jazzer, Вы писали:

J>1) Синтаксис объявления друга неправильный, должно быть:

J>
J>     template<typename T> friend void A::foo(B*);
J>

J>2) GCC 3.4.6 компилирует и всё работает

J>Что за компилятор?


Твою поправку не компилируют VC 2005 и 2008. Да, микрософт умеет удивлять
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[3]: Проблема с Dependent Name Lookup
От: jazzer Россия Skype: enerjazzer
Дата: 29.09.09 09:23
Оценка:
Здравствуйте, Кодт, Вы писали:

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


J>>1) Синтаксис объявления друга неправильный, должно быть:

J>>
J>>     template<typename T> friend void A::foo(B*);
J>>

J>>2) GCC 3.4.6 компилирует и всё работает

J>>Что за компилятор?


К>Твою поправку не компилируют VC 2005 и 2008. Да, микрософт умеет удивлять

ну, может, это бага гцц

А если заменить В на Т? тогда перестанет компилировать вызов, правда, потому что это не АDL все равно
Зато должно начать компилировать объявление френда
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: Проблема с Dependent Name Lookup
От: jazzer Россия Skype: enerjazzer
Дата: 29.09.09 09:26
Оценка: +1
Здравствуйте, Антибиотик, Вы писали:

А>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?

Да, раз уж на то пошло, это не ADL.
ADL будет в том случае, если В будет в А:

namespace A {
     template <typename T>
     void foo(T*p)
     {
       cout << "void foo(T*)\n";
     }
     
     class B {
     public:

          template<typename T> friend void foo(T*);
     private:
          int b_;
     };
}

int main()
{
  A::B b;
  foo(&b);
}
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]: Проблема с Dependent Name Lookup
От: The_Thing Россия
Дата: 29.09.09 09:32
Оценка:
Здравствуйте, Антибиотик, Вы писали:

Вот такой код на GCC работает (ниже), уверен, что на студии также!


#include <iostream>
using namespace std;

namespace A {
     template <typename T>
     void foo(T* val)
     {
       val->b_ = 2;
       cout << val->b_;
     }
};

class B {
public:

     friend void A::foo<>(B*);
private:
     int b_;
};

int main()
{
  B b;
  A::foo(&b);

  return 0;
}
Re[2]: Проблема с Dependent Name Lookup
От: Антибиотик Россия  
Дата: 29.09.09 09:35
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Антибиотик, Вы писали:


А>>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?

J>Да, раз уж на то пошло, это не ADL.
J>ADL будет в том случае, если В будет в А:

J>
J>namespace A {
J>     template <typename T>
J>     void foo(T*p)
J>     {
J>       cout << "void foo(T*)\n";
J>     }
     
J>     class B {
J>     public:

J>          template<typename T> friend void foo(T*);
J>     private:
J>          int b_;
J>     };
J>}

J>int main()
J>{
J>  A::B b;
J>  foo(&b);
J>}
J>

Да, согласен, что пример из первого поста на ADL не тянет ))
В первом посте фишка в том, что мне не нужны френдами абсолютно все функции foo, а нужна френдом только ее специализация для B.
Судя по всему, это на самом деле бага VC. Ну что же, идем на MS Connect ))
Re[2]: Проблема с Dependent Name Lookup
От: jazzer Россия Skype: enerjazzer
Дата: 29.09.09 09:36
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Антибиотик, Вы писали:


А>>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?

J>Да, раз уж на то пошло, это не ADL.
J>ADL будет в том случае, если В будет в А:
Ну и не только в этом случае, а во всех случаях, когда А становится ассоциированным (3.4.2/2) с В, напирмер, так:

J>
J>namespace A {
J>     template <typename T>
J>     void foo(T*p)
J>     {
J>       cout << "void foo(T*)\n";
J>     }
J>}
    
J>class B {
J>public:

J>     template<typename T> friend void A::foo(T*);
J>private:
J>     int b_;
J>};

J>int main()
J>{
J>  B b;
J>  foo(&b);
J>}
J>
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[4]: Проблема с Dependent Name Lookup
От: Антибиотик Россия  
Дата: 29.09.09 09:47
Оценка:
Здравствуйте, The_Thing, Вы писали:

T_T>Здравствуйте, Антибиотик, Вы писали:


T_T>Вот такой код на GCC работает (ниже), уверен, что на студии также!



T_T>
T_T>#include <iostream>
T_T>using namespace std;

T_T>namespace A {
T_T>     template <typename T>
T_T>     void foo(T* val)
T_T>     {
       val->>b_ = 2;
T_T>       cout << val->b_;
T_T>     }
T_T>};

T_T>class B {
T_T>public:

T_T>     friend void A::foo<>(B*);
T_T>private:
T_T>     int b_;
T_T>};

T_T>int main()
T_T>{
T_T>  B b;
T_T>  A::foo(&b);

T_T>  return 0;
T_T>}

T_T>

Согласен, что данный код будет работать и в студии, если при вызове foo указать пространство имен. Причина создания данной темы состоит в том, почему VC кушает вызов foo и без неймспейса.
Re[5]: Проблема с Dependent Name Lookup
От: The_Thing Россия
Дата: 29.09.09 10:24
Оценка:
Здравствуйте, Антибиотик, Вы писали:

А>Согласен, что данный код будет работать и в студии, если при вызове foo указать пространство имен. Причина создания данной темы состоит в том, почему VC кушает вызов foo и без неймспейса.


Может и не баг, надо стандарт глянуть раздел дружественных функций и посмотреть, что там сказано про пространство имен (может и ничего не сказано, тогда баг).
Re[2]: Проблема с Dependent Name Lookup
От: Caracrist https://1pwd.org/
Дата: 29.09.09 14:03
Оценка:
Здравствуйте, jazzer, Вы писали:

J>1) Синтаксис объявления друга неправильный, должно быть:

J>
J>     template<typename T> friend void A::foo(B*);
J>



template<typename T> friend void A::foo<T>(B*);

~~~~~
~lol~~
~~~ Single Password Solution
Re[2]: Проблема с Dependent Name Lookup
От: Erop Россия  
Дата: 29.09.09 17:04
Оценка:
Здравствуйте, jazzer, Вы писали:

J>1) Синтаксис объявления друга неправильный, должно быть:

J>
J>     template<typename T> friend void A::foo(B*);
J>


Что-то тут не так. Как объявляемая функция зависит от T? И если не зависит, то почему тут шаблон?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Проблема с Dependent Name Lookup
От: Николай Ивченков  
Дата: 29.09.09 22:55
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Антибиотик, Вы писали:


А>>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?


J>1) Синтаксис объявления друга неправильный, должно быть:

J>
J>     template<typename T> friend void A::foo(B*);
J>

Неправда твоя, оба варианта допустимы:

14.8.1/2:
[q]A template argument list may be specified when referring to a specialization of a function template
— when a function is called,
— when the address of a function is taken, when a function initializes a reference to function, or when a
pointer to member function is formed,
— in an explicit specialization,
— in an explicit instantiation, or
in a friend declaration.
Trailing template arguments that can be deduced (14.8.2) may be omitted from the list of explicit templatearguments. If all of the template arguments can be deduced, they may all be omitted; in this case, the empty template argument list <> itself may also be omitted.
Re: Проблема с Dependent Name Lookup
От: Николай Ивченков  
Дата: 29.09.09 23:08
Оценка:
Антибиотик:

А>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?


Текущий стандарт недостаточно чётко описывает, какие именно friend-объявления могут рассматриваться при аргументо-зависимом поиске. По этому поводу есть defect report — DR 143. Если брать за основу уточнённые формулировки, то относительно данного кода можно сказать, что через ADL foo искаться не будет.
Re[3]: Проблема с Dependent Name Lookup
От: jazzer Россия Skype: enerjazzer
Дата: 30.09.09 00:15
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

J>>1) Синтаксис объявления друга неправильный, должно быть:

НИ>Неправда твоя, оба варианта допустимы:

Да, я не понял, что ему именно специализацию нужно сделать другом, а не весь шаблон.
Ну и опечатался заодно
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]: Проблема с Dependent Name Lookup
От: jazzer Россия Skype: enerjazzer
Дата: 30.09.09 01:00
Оценка:
Здравствуйте, Erop, Вы писали:

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


J>>1) Синтаксис объявления друга неправильный, должно быть:

J>>
J>>     template<typename T> friend void A::foo(B*);
J>>


E>Что-то тут не так. Как объявляемая функция зависит от T? И если не зависит, то почему тут шаблон?


Это опечатка, должно было быть Т
Я не понял, что Антибиотик хотел именно специализацию сделать френдом.

А так — это просто шаблонная функция, у которой параметр шаблона не фигурирует в аргументах (но используется где-то внутри, например), это совершенно валидно.
Ну и эта функция, я думаю, инжектируется в объемлющее В пространство имен, хотя настаивать на этом не буду — дело с инжекцией традиционно темное.
Другое дело, что в таком случае получается не совсем та функция. Которая вообще не определена
Так что то ,что он вызывает нашу функци — это, наверное, баг этой версии гцц.
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]: Проблема с Dependent Name Lookup
От: jazzer Россия Skype: enerjazzer
Дата: 30.09.09 02:25
Оценка:
Здравствуйте, Антибиотик, Вы писали:

А>В первом посте фишка в том, что мне не нужны френдами абсолютно все функции foo, а нужна френдом только ее специализация для B.


Ясно, я этого не осознал
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...
Пока на собственное сообщение не было ответов, его можно удалить.