class X;
class Y
{
friend void f(X const &);
};
void g(X const &);
int main()
{
f(getX());
}
Здесь f находится в ::, единственное отличие ее от g — она скрыта от простого поиска. Верно? Но ведь ADL в этом случае рассматривает :: как associated namespace класса X и должна найти функцию!
7.3.1.2/3
Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope (either before or after the class declaration granting friendship). If a friend function is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2). When looking for a prior declaration of a class or a function declared as a friend, and when the name of the friend class or function is neither a qualified name nor a template-id, scopes outside the innermost enclosing namespace scope are not considered.
Причем у функции, являющейся другом Y, но не имеющей аргументов типа Y, вполне может быть причина для существования. Например, там внутри Y::instance().somePrivateSubobject().process(x);
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, remark, Вы писали:
R>>
R>>char engine(...);
R>>template<typename, int> struct magic;
R>>typedef magic<char, -1> magicc;
R>>template<typename type = int, int id = sizeof(engine(*(magicc*)0, *(type*)0))>
R>>struct magic
R>>{
R>> friend int engine(magicc&, type&);
R>> static const int val = id;
R>>};
R>>int main()
R>>{
R>> char a[magic<>::val != magic<>::val ? 1 : -1];
R>>}
R>>
E>Вот смотри. Я так тебя понял что ты ждёшь, что выделенное неравенство будет соблюдено. E>Вот и поясни (без всяких там ссылок на тонкости стандарта), как, по твоему мнению обстоит дело. E>Где именно и какие именоо инстанциации инстанциируются. То есть укажи пожалуйста место POI для всех участвующих в процессе шаблонов.
E>А то я что-то никак не въеду
все просто.
он не будет всегда разным он будет разным при первом и втором упоминании, в следущих разах будет всегда 4
char engine(...); вот функция которая используется в этом шаблоне. int id = sizeof(engine(*(magicc*)0, *(type*)0)
но как только мы инстанциировали класс magic, то появляется magic — friend int engine(magicc&, type&);
а он как мы видем уже возвращает не char а int (1 vs 4)
и вот во втором включении мы видим уже int engine(magicc&, type&); эту функцию.
для счетчика, где каждый раз обновляется val я написал вот так.
R>>>char engine(...);
R>>>template<typename, int> struct magic;
R>>>typedef magic<char, -1> magicc;
R>>>template<typename type = int, int id = sizeof(engine(*(magicc*)0, *(type*)0))>
R>>>struct magic
R>>>{
R>>> friend int engine(magicc&, type&);
R>>> static const int val = id;
R>>>};
R>>>int main()
R>>>{
R>>> char a[magic<>::val != magic<>::val ? 1 : -1];
R>>>}
R>>>
E>>Вот смотри. Я так тебя понял что ты ждёшь, что выделенное неравенство будет соблюдено. E>>Вот и поясни (без всяких там ссылок на тонкости стандарта), как, по твоему мнению обстоит дело. E>>Где именно и какие именоо инстанциации инстанциируются. То есть укажи пожалуйста место POI для всех участвующих в процессе шаблонов.
IRO>все просто.
Спасибо за разъяснения
К сожалению, ты ответил не на мой вопрос.
Свой вопрпос я выделил полужирным, для удобства.
А замысел ремарка я понял сразу. Только мне кажется, что это всё глюки компилятора
IRO>но как только мы инстанциировали класс magic, то появляется magic — friend int engine(magicc&, type&);
Прекрасно! Где будет POI? Перед функцией main? Или после?
Если перед, то почему не будет действовать на первое же упоминание, если после, то почему будет действовть на второе?..
3E>>А то я что-то никак не въеду
IRO>вот тут!
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: всё ещё прикольнее, чем кажется на первый взгляд!
Здравствуйте, remark, Вы писали:
R>Тем не менее похоже, что не работает это исключительно на Comeau. И это остаётся рабочим вариантом на msvc71/msvc80/gcc34/gcc41/icc70/icc80/edg. Впечатляет, правда? Не работает только на самых свежих фронт-ендах edg. R>Имхо список компиляторов достаточен даже для включения в boost
На самом деле прикольно, что глюк совпадает. Я бы озаботился вопросом о переиспользовании чужого кода...
Чтобы было понятнее о чём таки я, надо попробовать объяснить как же всё-таки работает компилятор?
Чтобы было легче, надо ответить на уточнённый вспомогательный вопрос
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: всё ещё прикольнее, чем кажется на первый взгляд!
Уж не намекаете ли ва на то, что злые коммерческие дядьки из Microsoft и Intel использовали(читай спиз$или) беззащитный, открытый GPL-ый(?) код синтаксического анализа gcc? И теперь цинично делают деньги? Как такое можно подумать.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[4]: всё ещё прикольнее, чем кажется на первый взгляд!
Здравствуйте, Ka3a4oK, Вы писали:
KK>Уж не намекаете ли ва на то, что злые коммерческие дядьки из Microsoft и Intel использовали(читай спиз$или) беззащитный, открытый GPL-ый(?) код синтаксического анализа gcc? И теперь цинично делают деньги? Как такое можно подумать.
Я намекаю на то, что не совсем понятно как хитро так работают инстанциаторы шаблонов в разных компиляторах.
Наверняка авторы разных компиляторов не только решали схожие задачи и читали схожиекниги, но и смтрели на изделия конкурентов. И то, что глюк столь распрорстранён наверняка имеет какую-то пичину. Если это не банальный цельнотянутый код (я в это не верю, так как даже если код тянут, то его ремасерят, особенно, если он живёт много версий и поддерживается и развивается), то навкрняка есть какая-то довольно глубокая и нетривиальная причина...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Невероятно, но факт! Не константные значения в компайл-т
namespace compile_time_flag
{
struct yes{};
struct no{char _no[2];};
no check(...);
template <class,class,int> struct flag;
template <class T> T& make_ref();
template <class flag_type,class type = yes, int id = sizeof(check(make_ref<flag<flag_type,no,-1> >(), make_ref<type>()))==sizeof(yes)>
struct flag
{
friend yes check(flag<flag_type,no,-1>&,type&);
static const int IsTrue = id;
};
}
#include <iostream>
int main()
{
char a[compile_time_flag::flag<int>::IsTrue != compile_time_flag::flag<int>::IsTrue ? 1 : -1];//Первый 0, второй 1static const int i = compile_time_flag::flag<char>::IsTrue;//0static const int j = compile_time_flag::flag<double>::IsTrue;//0static const int k = compile_time_flag::flag<double>::IsTrue;//1static const int l = compile_time_flag::flag<char>::IsTrue;//1static const int m = compile_time_flag::flag<char>::IsTrue;//1
std::cout<<i<<j<<k<<l<<m;//00111
}
Все работает на 8.0 студии именно так, как мне хочется. Естественно, захотелось, чтобы и под другими компиляторами работало. remark обещает работоспособность под кучей компиляторов, кроме Comeau. Пытался найти объяснение. Находил нечто похожее, например здесь
для Comeau Online оба значения равны 0! Что означает, что при вычислении default параметра id всегда используется функция с эллипсисом. Несмотря на то, что ADL должен найти friend функцию(хотя бы в одном месте).
Итак, объясните мне, почему Comeau работает так(желательно с указанием стандарта), или относим Comeau к не поддерживающим стандарт компиляторам и еще раз апплодируем идее
Ну, и как оно должно все-таки работать, желательно — список действий компилятора.
Всем заранее спасибо
<вырезано, дабы сохранить место на сервере>
Re[2]: Невероятно, но факт! Не константные значения в компай
Здравствуйте, tilarids, Вы писали:
T>для Comeau Online оба значения равны 0! Что означает, что при вычислении default параметра id всегда используется функция с эллипсисом. Несмотря на то, что ADL должен найти friend функцию(хотя бы в одном месте).
T>Итак, объясните мне, почему Comeau работает так(желательно с указанием стандарта), или относим Comeau к не поддерживающим стандарт компиляторам и еще раз апплодируем идее T>Ну, и как оно должно все-таки работать, желательно — список действий компилятора.
Comeau судя по всему как раз единственный делает правильно. А все остальные компиляторы очень подозрительно делают одну и ту же ошибку. Хотя вопрос очень тёмный и с уверенностью здесь сказать что-либо сложно.
Как это должно работать (как делает Comeau).
Если функция может быть найдена с помощью обычного поиска или ADL, то она должна быть найдена в любом случае. Результат поиска не должен завистеть ни от чего, в том числе от того какие шаблоны были инстанциированы до этой точки.
Как делают все остальные.
Функция находится с помощью ADL только после того, как шаблон её содержащий был инстанциирован.
Т.е. компилятор должен в данном случае при осуществлении ADL инстанциировать все классы, которые относятся к типу каждого параметра функции и посмотреть, не появилось ли новой подходящей функции во время этого инстанциирования. Как-то так.
Здравствуйте, remark, Вы писали:
R>Comeau судя по всему как раз единственный делает правильно. А все остальные компиляторы очень подозрительно делают одну и ту же ошибку. Хотя вопрос очень тёмный и с уверенностью здесь сказать что-либо сложно.
R>Как это должно работать (как делает Comeau). R>Если функция может быть найдена с помощью обычного поиска или ADL, то она должна быть найдена в любом случае. Результат поиска не должен завистеть ни от чего, в том числе от того какие шаблоны были инстанциированы до этой точки.
R>Как делают все остальные. R>Функция находится с помощью ADL только после того, как шаблон её содержащий был инстанциирован.
R>Т.е. компилятор должен в данном случае при осуществлении ADL инстанциировать все классы, которые относятся к типу каждого параметра функции и посмотреть, не появилось ли новой подходящей функции во время этого инстанциирования. Как-то так.
R>
Comeau Online демонстрирует вообще замечательное поведение — там просто ADL не работает. То бишь:
namespace compile_time_flag
{
struct yes{};
struct no{char _no[2];};
no check(...);
template <class,class,int> struct flag;
template <class T> T& make_ref();
template <class flag_type,class type = yes, int id = sizeof(check(make_ref<flag<flag_type,no,-1> >(), make_ref<type>()))==sizeof(yes)>
struct flag
{
friend yes check(flag<flag_type,no,-1>&,type&);
static const int IsTrue = id;
};
}
#include <iostream>
int main()
{
char a[compile_time_flag::flag<int>::IsTrue ==0 ? 1 : -1];
char b[compile_time_flag::flag<int>::IsTrue ==0 ? 1 : -1];
(void)a;
(void)b;
}
Выдает только 1 warning о нетемплейтовой friend функции — все прекрасно компилится. Хотя ADL должен приводить к тому, что будет найдена
friend yes check(flag<flag_type,no,-1>&,type&);
А находит функцию с эллипсисом.
Так что я, наверное, все же реализую подобный подход Вот только скорее не отсюда, а с boost lists
<вырезано, дабы сохранить место на сервере>
Re: Невероятно, но факт! Не константные значения в компайл-т
Здравствуйте, tilarids, Вы писали:
T>Comeau Online демонстрирует вообще замечательное поведение — там просто ADL не работает.
LROTF
Ты тут просто неправильно написал. Ты не ту функцию другом объявляешь или точнее другом не того класса.
Хинт: тип flag<no> и тип flag<yes> — совершенно разные типы. При ADL поиске через один тип не будут находится функции связанные с другим типом.
Если не изменяет память, в этом топике я приводил решение для этой проблемы.
Здравствуйте, Yoh Asakura, Вы писали:
YA>Все что невероятно — заканчивается обычно тем, что сия магия перестает работать на выпущенных позже компиляторах.
Сия магия заканчивается обычно тем, что производителям компиляторов приходится пожизненно поддерживать флаги для обратной совместимости поведения. Даже если это было не стандартное поведение или просто баг.
Здравствуйте, Yoh Asakura, Вы писали:
YA>Не согласен, ибо тон задают создатели стандарта и производители компилятора, а все остальные вынуждены писать в своем коде обходные макросы =)
Какие есть примеры, когда производитель массового продукта не обратно совместимо менял поведение и рушил тем самым клиентский код?
Производители массового продукта подобные вещи наружу не выносят, а отдают откомпелированный код.
А за примерами идти надо в OpenSource — так он наполнен подобным, когда изменение в GCC по исправлению баги приводит к тому, что даже известные OpenSource библиотеки не собираются, не говоря уже попытке собрать старую версию ядра новым компилятором...
Здравствуйте, tilarids, Вы писали:
T>Итак, объясните мне, почему Comeau работает так(желательно с указанием стандарта), или относим Comeau к не поддерживающим стандарт компиляторам и еще раз апплодируем идее T>Ну, и как оно должно все-таки работать, желательно — список действий компилятора. T>Всем заранее спасибо
ИМХО этот код работать не должен. Это если по стандарту.
Чтобы убедить меня в обратном, укажи пожалуйста в каких именно местах единицы трансляции должны находиться POI каких именно шаблонов,
чтобы в этой строчке
"compile_time_flag::flag<int>::IsTrue" компилировалось по разному слева и справа от оператора !=.
То что на остальных компиляторах этот хак работает не о чём, кроме неаккуратного использования в этих компиляторах статических переменных не говорит
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Невероятно, но факт! Не константные значения в компай
Здравствуйте, remark, Вы писали:
R>Сия магия заканчивается обычно тем, что производителям компиляторов приходится пожизненно поддерживать флаги для обратной совместимости поведения. Даже если это было не стандартное поведение или просто баг.
R>
Не, ну это ты себе льстишь всё-таки. Хотя хак классный, жалко, что не по стандарту
Для того, чтобы производители компилятора поддерживали в следующих версиях багу, как фичу, требуется, чтобы багу начали использовать таки массово
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Невероятно, но факт! Не константные значения в компай
Здравствуйте, remark, Вы писали:
R>Какие есть примеры, когда производитель массового продукта не обратно совместимо менял поведение и рушил тем самым клиентский код?
Фирму Microsoft знаешь?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском