Здравствуйте, Erop, Вы писали:
E>Здравствуйте, remark, Вы писали:
R>>Вот это вообще не понял. R>>Да, я просто объявляю нешаблонную функцию, но при этом никакими дырками не пользуюсь. R>>Примеры таких объявлений можно увидеть и у Страуструпа, и у Саттера и у др.
E>Дырка состоит в том, что у инстанцирования шаблонного класса есть побочный эффект -- появляется объявление нешаблонной функции в объемлющем пространстве имён. На что именно влияет это объявление,а на что не влияет -- это вопрос очень тонкий.
Не поленюсь ещё раз переписать пример, который приводят и Страуструп и Саттер и др.:
Я надеюсь его работоспособность не вызывает вопросов. Иначе это уже не ко мне.
Имхо, если повнимательнее поглядеть на пример, то всё становится достаточно прозрачно.
В POI для конкретной специализации friend function выносится в объемлющее пространство. И "ниже" POI эта function может вызываться и участвовать в перегрузке на равне со всеми остальными.
R>>"ComeauTest.c", line 15: error: the size of an array must be greater than zero
R>> char a[magic<>::val != magic<>::val ? 1 : -1];
R>> ^
R>>Ошибка ни о чём не говорит. Где и что конкретно не так.
L_L>Да что ты? Она говорит о том, что magic<>::val он один и не меняется. Или нет?
Ну это-то я понял из ошибки
Но она не говорит о том, где и что конкретно я нарушил из стандарта.
А по поводу глюков конкретного компилятора — так Comeau пока в заметном меньшенстве, т.ч. если у какого компилятора глюки, так это как раз у него
R>>Аааа... ты про это мне хотел сказать???
L_L>Не, я хотел о другом — забавно, я вчера пробовал — и он орал о разыменовании нулевых указателей. Похоже, что это он замечает в relaxed mode.
Ну что вы все к ним прицепились. Я уже написал, пуристы могут заменить на вызов функции, возвращающей ссылку
К сути вопроса это малол относится...
L_L>А вообще, так как всем нам, похоже, одинаково некогда/лень ковыряться в стандарте и искать обоснований тех или иных утверждений, лучше подождать авторитетных мнений: Андрея Тарасевича, Павла Кузнецова, elcste (порядок указания имен произвольный ). Можно спросить на comp.lang.c++.moderated. L_L>Лично для меня очевидно, что поиск имен должен работать всегда одинаково и не зависеть от того, что и сколько раз инстанцировалось.
Я надеюсь его работоспособность не вызывает вопросов. Иначе это уже не ко мне.
Имхо, если повнимательнее поглядеть на пример, то всё становится достаточно прозрачно.
В POI для конкретной специализации friend function выносится в объемлющее пространство. И "ниже" POI эта function может вызываться и участвовать в перегрузке на равне со всеми остальными.
Что здесь вызывает вопросы?
То, что эту функцию можно вызывать "ниже" POI — это факт. А раз можно вызывать, значит она есть, а раз есть, значит она участвует в перегрузке на равне со всеми остальными, т.к. никаких таких особенных функций в языке нет (как тут некоторые пытались предложить), которые можно вызывать, но в перегрузке не участвуют.
Ведь если просто объявить дополнительную перегрузку функции "руками", то ведь будет зависеть до неё делать POI или после. Ведь эта основная суть POI, что шаблон видит всё, что "выше" POI.
R>>>Сколько это определение шаблонного класса должно _сразу_ вынести функций в глобальное пространство имён? Для всего бесконечного возможного набора типов, которыми когда-либо могут параметризовать этот шаблон? PC>>Да именно так, т.е. равнозначно этому (кроме прав доступа) NB>
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Шахтер, Вы писали:
Ш>>1) Я пока не увидел доказательства того, что это standard-compliant поведение. По-моему -- баг. Ш>>2) Если это не баг, то это дыра в стандарте. Срочно фиксить стандарт. Ш>>3) Пользоваться такими изобретениями в реальной работе категорически нельзя. Ломиком по рукам.
К>Больше всего это похоже на нарушение ODR.
Нет-нет! Подождите!
Где ж тут нарушение ODR? Для какого объявления есть более одного определения???
ODR — это как раз то, с чем пришлось побороться при реализации.
И имхо я его побороол, т.к. у меня получаются просто разные типы. Фактически это равнозначно такому _рукописному_ коду:
magic<0>::val;
magic<1>::val;
magic<2>::val;
Тут очевидно нет никакого нарушения ODR — просто обычный код.
А по поводу того, что написано в аргументе шаблона по-умолчанию — ну так это же аргумент (сравните с параметром)! А аргумент относится к call-side. Т.е. фактически равнозначно:
Нет-нет-нет. Тоже не cогласен.
typdef запоминает конкретный template-id, template он не запоминает. Если аргументы не указаны, значит в template-id используются аргументы по-умолчанию. Всё. Точка.
Тут всё однозначно! Никаких разночтений и вопросов!
Здравствуйте, remark, Вы писали:
Ш>>С чего бы это? У тебя тип параметра не совпадает с типом, в котором продекларирован engine().
и че с того?
если объявление идет в глобально пространство, то все нормально.
если в локальное, то передачу по ссылке в объявлении френда можно заменить на передачу по значению.
R>Отвечаю на конкретный вопрос
R>Похоже тут ты прав. R>Тогда предлагаю сделать так (тут вроде в этом плане всё чисто):
Здравствуйте, Roman Odaisky, Вы писали:
R>>участвует в перегрузке наравне со всеми остальными
RO>Или я что-то путаю, или функции, которые находит только ADL, имеют более низкий приоритет?
увы
сам офигел когда узнал, но простой поиск и ADL имеют одинаковый приоритет.
то есть сначала происходит поиск имен (все поиски) а потом оверлоад ресолюшн.
так что будте осторожны с выборос жадных перегрузок.
Re[8]: Невероятно, но факт! Не константные значения в компай
RO>Зависит ли здесь поиск имен от того, чем инстанцируется C? По-моему, очень даже зависит.
Что ты хотел сказать этим примером-то? Например, я инстанцировал C типом int, что ADL тут сработает? Или каким-то еще классом (и при этом инстанцировал C неважно каким типом) что, ADL тут тебе поможет????
Of course, the code must be complete enough to compile and link.
Re[7]: Невероятно, но факт! Не константные значения в компай
Здравствуйте, remark, Вы писали:
К>>Больше всего это похоже на нарушение ODR.
R>Нет-нет! Подождите! R>Где ж тут нарушение ODR? Для какого объявления есть более одного определения???
Мда, действительно... значит, не оно.
Хотя ситуация, когда одно и то же выражение в разных частях одного и того же scope резолвится по-разному — настораживает...
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[11]: Невероятно, но факт! Не константные значения в компа
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Аноним, Вы писали:
А>>Я думаю, Комо, а скорее всего, последний фронт-энд от едг (у Комо он какой-то древний уже). Уж если ЕДГ и глючит, то в совсем уж нетривиальных моментах. А>>Автор упомянул ЕДГ, но я не понял, что это значит — купить его простым смертным — малореально
R>EDG C++ это компилирует R>здесь
R>
Здравствуйте, Lorenzo_LAMAS, Вы писали:
RO>>Зависит ли здесь поиск имен от того, чем инстанцируется C? По-моему, очень даже зависит.
L_L>Что ты хотел сказать этим примером-то? Например, я инстанцировал C типом int, что ADL тут сработает? Или каким-то еще классом (и при этом инстанцировал C неважно каким типом) что, ADL тут тебе поможет????
Я не об этом… Если компилятор видит someFunctionDeclaredAsFriend_OrPerhapsNotYet_(someExpr()), то его понимание этого зависит от того, чем инстанцировался класс ранее по ходу и инстанцировался ли вообще. Например:
Здравствуйте, night beast, Вы писали:
R>>>участвует в перегрузке наравне со всеми остальными
RO>>Или я что-то путаю, или функции, которые находит только ADL, имеют более низкий приоритет?
NB>увы NB>сам офигел когда узнал, но простой поиск и ADL имеют одинаковый приоритет. NB>то есть сначала происходит поиск имен (все поиски) а потом оверлоад ресолюшн. NB>так что будте осторожны с выборос жадных перегрузок.
А как же 3.4.2/2a («If the ordinary unqualified lookup of the name finds the declaration of a class member function, the associated namespaces and classes are not considered»)? Хотя тут тоже неясно — причем здесь цласс мембер фунцтион?
Я поскипал твои примеры, извини, но мне уже влом их смотреть, так же как и тебе, видимо, влом понять, о чем я говорю. Поиск имен, АДЛ _не_ _зависят_ от того, писал ли ты A<someType> строчкой выше до fun(somArg). АДЛ зависит от типа somArg. И используя этот тип АДЛ найдет нужную функцию и без A<someType> строчкой выше. Я говорил об этом. И magic<>::val повторенный сколько угодно раз в этом злосчастном объявлении массива будет одним и тем же. И если у Вижуала это не так — это его проблемы и тех, кто хочет юзать такие трики.
Of course, the code must be complete enough to compile and link.
Re[11]: Невероятно, но факт! Не константные значения в компа
Здравствуйте, Roman Odaisky, Вы писали:
RO>А как же 3.4.2/2a («If the ordinary unqualified lookup of the name finds the declaration of a class member function, the associated namespaces and classes are not considered»)? Хотя тут тоже неясно — причем здесь цласс мембер фунцтион?
по счастью это можно проверить.
template<typename T> void foo (T,T);
namespace ns {
struct test {};
template<typename T> void foo (T,T);
}
int main () {
ns::test x;
foo (x,x);
}
ИМХО.
После того, как здесь не менее 10 раз упомянули, что friend объявление не добавляет имя, которое может найти обычный поиск имен (не АДЛ), странно писать testy1(x) — почему тут что-то должно быть найдено? testy0() а почему тут?
А уж про нахождения имен после инстанцирования старыми версиями gcc и вижуалом — вообще говорить надоело.
Of course, the code must be complete enough to compile and link.
Так как у тебя нет объявлений функций друзей вне классов, то работать будет только то, что найдет ADL. Про ADL — читай в стандарте.
Выражения, где ты берешь адрес функции — есс-но не компилируются, т.к. не имеют к АДЛ никакого отношения. Выражения с квалификацией — тоже.
When an unqualified name is used as the postfix-expression in a function call (5.2.2), other namespaces not
considered during the usual unqualified lookup (3.4.1) may be searched, and namespace-scope friend function
declarations (11.4) not otherwise visible may be found.
#include <iostream>
namespace ns
{
class X
{
public:
friend void testxx(X const& x)
{
std::cout << "An X: " << &x << std::endl;
}
friend void testx()
{
std::cout << "Just a test." << std::endl;
}
};
}
class Y
{
public:
friend void testyy(Y const& y)
{
std::cout << "A Y: " << &y << std::endl;
}
friend void testy()
{
std::cout << "Just a test." << std::endl;
}
};
int main()
{
ns::X x;
testxx(x);
// ns::testxx(x);
Y y;
testyy(y);
// ::testyy(x);
/* std::cout << (void *)&testy << std::endl;
std::cout << (void *)&testyy << std::endl;
std::cout << (void *)&ns::testx << std::endl;
std::cout << (void *)&ns::testxx << std::endl;
testy();//здесь нет никаких аргументов == не может найти такое имя.
ns::testx();*/
}
Of course, the code must be complete enough to compile and link.