#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, то почему нету ошибки компиляции?
Здравствуйте, Антибиотик, Вы писали:
1. не компилируется, так как foo не найдена, надо A::foo — так всё работает.
2. не понял при чём тут B.
А>имеется следующий код: А>
А>который нормально компилируется, но почему-то не работает так, как ожидается. Точнее, функция foo фактически не вызывается. А>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?
Здравствуйте, Антибиотик, Вы писали:
А>имеется следующий код: А>который нормально компилируется,
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... — если захочешь в гугле искать, чтоб проблем не было.
Здравствуйте, Антибиотик, Вы писали:
А>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?
1) Синтаксис объявления друга неправильный, должно быть:
Здравствуйте, The_Thing, Вы писали:
T_T>Здравствуйте, Антибиотик, Вы писали: T_T>1. не компилируется, так как foo не найдена, надо A::foo — так всё работает. T_T>2. не понял при чём тут B.
1. используется компилятор Microsoft Visual C++ 2008 Express, в нем все нормально компилируется
2. это упрощенный пример более сложного кода, суть в том, что функция foo вызывается с аргументом типа B. Чтобы было понятнее, пусть функция foo выглядит так:
J>>2) GCC 3.4.6 компилирует и всё работает
J>>Что за компилятор?
К>Твою поправку не компилируют VC 2005 и 2008. Да, микрософт умеет удивлять
ну, может, это бага гцц
А если заменить В на Т? тогда перестанет компилировать вызов, правда, потому что это не АDL все равно
Зато должно начать компилировать объявление френда
Здравствуйте, Антибиотик, Вы писали:
А>Вопрос: если это пример 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, Вы писали:
J>Здравствуйте, Антибиотик, Вы писали:
А>>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции? J>Да, раз уж на то пошло, это не ADL. J>ADL будет в том случае, если В будет в А:
J>
Да, согласен, что пример из первого поста на ADL не тянет ))
В первом посте фишка в том, что мне не нужны френдами абсолютно все функции foo, а нужна френдом только ее специализация для B.
Судя по всему, это на самом деле бага VC. Ну что же, идем на MS Connect ))
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, Антибиотик, Вы писали:
А>>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции? J>Да, раз уж на то пошло, это не ADL. J>ADL будет в том случае, если В будет в А:
Ну и не только в этом случае, а во всех случаях, когда А становится ассоциированным (3.4.2/2) с В, напирмер, так:
J>
Согласен, что данный код будет работать и в студии, если при вызове foo указать пространство имен. Причина создания данной темы состоит в том, почему VC кушает вызов foo и без неймспейса.
Здравствуйте, Антибиотик, Вы писали:
А>Согласен, что данный код будет работать и в студии, если при вызове foo указать пространство имен. Причина создания данной темы состоит в том, почему VC кушает вызов foo и без неймспейса.
Может и не баг, надо стандарт глянуть раздел дружественных функций и посмотреть, что там сказано про пространство имен (может и ничего не сказано, тогда баг).
Что-то тут не так. Как объявляемая функция зависит от T? И если не зависит, то почему тут шаблон?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, Антибиотик, Вы писали:
А>>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?
J>1) Синтаксис объявления друга неправильный, должно быть: 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.
Антибиотик:
А>Вопрос: если это пример Argument Dependent Name Lookup, то почему функция не вызывается, если это не ADNL, то почему нету ошибки компиляции?
Текущий стандарт недостаточно чётко описывает, какие именно friend-объявления могут рассматриваться при аргументо-зависимом поиске. По этому поводу есть defect report — DR 143. Если брать за основу уточнённые формулировки, то относительно данного кода можно сказать, что через ADL foo искаться не будет.
E>Что-то тут не так. Как объявляемая функция зависит от T? И если не зависит, то почему тут шаблон?
Это опечатка, должно было быть Т
Я не понял, что Антибиотик хотел именно специализацию сделать френдом.
А так — это просто шаблонная функция, у которой параметр шаблона не фигурирует в аргументах (но используется где-то внутри, например), это совершенно валидно.
Ну и эта функция, я думаю, инжектируется в объемлющее В пространство имен, хотя настаивать на этом не буду — дело с инжекцией традиционно темное.
Другое дело, что в таком случае получается не совсем та функция. Которая вообще не определена
Так что то ,что он вызывает нашу функци — это, наверное, баг этой версии гцц.
Здравствуйте, Антибиотик, Вы писали:
А>В первом посте фишка в том, что мне не нужны френдами абсолютно все функции foo, а нужна френдом только ее специализация для B.