Re[8]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 09.02.07 05:20
Оценка:
Здравствуйте, Erop, Вы писали:

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


R>>Вот это вообще не понял.

R>>Да, я просто объявляю нешаблонную функцию, но при этом никакими дырками не пользуюсь.
R>>Примеры таких объявлений можно увидеть и у Страуструпа, и у Саттера и у др.

E>Дырка состоит в том, что у инстанцирования шаблонного класса есть побочный эффект -- появляется объявление нешаблонной функции в объемлющем пространстве имён. На что именно влияет это объявление,а на что не влияет -- это вопрос очень тонкий.


Не поленюсь ещё раз переписать пример, который приводят и Страуструп и Саттер и др.:

template<typename type>
struct complex
{
//...
friend complex& operator + (complex, complex) {...}
//...
};

complex<int> c1, c2;
complex<int> c3 = c1 + c2;


Я надеюсь его работоспособность не вызывает вопросов. Иначе это уже не ко мне.
Имхо, если повнимательнее поглядеть на пример, то всё становится достаточно прозрачно.
В POI для конкретной специализации friend function выносится в объемлющее пространство. И "ниже" POI эта function может вызываться и участвовать в перегрузке на равне со всеми остальными.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 09.02.07 05:30
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

R>>

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>Лично для меня очевидно, что поиск имен должен работать всегда одинаково и не зависеть от того, что и сколько раз инстанцировалось.

Вот гляди:

template<typename type>
struct complex
{
//...
friend complex& operator + (complex, complex) {...}
//...
};

complex<int> c1, c2;
complex<int> c3 = c1 + c2;



Я надеюсь его работоспособность не вызывает вопросов. Иначе это уже не ко мне.
Имхо, если повнимательнее поглядеть на пример, то всё становится достаточно прозрачно.
В POI для конкретной специализации friend function выносится в объемлющее пространство. И "ниже" POI эта function может вызываться и участвовать в перегрузке на равне со всеми остальными.

Что здесь вызывает вопросы?
То, что эту функцию можно вызывать "ниже" POI — это факт. А раз можно вызывать, значит она есть, а раз есть, значит она участвует в перегрузке на равне со всеми остальными, т.к. никаких таких особенных функций в языке нет (как тут некоторые пытались предложить), которые можно вызывать, но в перегрузке не участвуют.

Ведь если просто объявить дополнительную перегрузку функции "руками", то ведь будет зависеть до неё делать POI или после. Ведь эта основная суть POI, что шаблон видит всё, что "выше" POI.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 09.02.07 05:32
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, Pavel Chikulaev, Вы писали:


NB>
R>>>template<typename type>
R>>>struct magic
R>>>{
R>>>    friend int engine(type);
R>>>};
NB>


R>>>Сколько это определение шаблонного класса должно _сразу_ вынести функций в глобальное пространство имён? Для всего бесконечного возможного набора типов, которыми когда-либо могут параметризовать этот шаблон?

PC>>Да именно так, т.е. равнозначно этому (кроме прав доступа)
NB>
PC>>template<typename type>
PC>>int engine(type);

PC>>template<typename type>
PC>>struct magic
PC>>{
PC>>};
NB>


NB>свой резон в этом есть. но что компилятор должен делать в таком случае:

NB>
NB>template<typename T>
NB>struct magic
NB>{
NB>    typedef typename remove_ref<T>::type type;

NB>    friend int engine(type);
NB>};
NB>


Да, пожалуйста, Pavel Chikulaev, прокоментируйте!

Или если есть явные специализации шаблона, в которых нет этого френда?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 09.02.07 06:00
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>С чего бы это? У тебя тип параметра не совпадает с типом, в котором продекларирован engine().


Отвечаю на конкретный вопрос

Похоже тут ты прав.
Тогда предлагаю сделать так (тут вроде в этом плане всё чисто):

char engine(...);

template<typename type>
struct magic_base
{
    friend int engine(magic_base<type>&, type&) {return 0;};
};

template<typename type> type& create();

template<typename type = int, int id = sizeof(engine(create<magic_base<type> >(), create<type>() ))>
struct magic : magic_base<type>
{
    static const int val = id;
};

int main()
{
    char a[magic<>::val != magic<>::val ? 1 : -1];
    (void)a;
}




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 09.02.07 06:08
Оценка:
Здравствуйте, Кодт, Вы писали:

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


Ш>>1) Я пока не увидел доказательства того, что это standard-compliant поведение. По-моему -- баг.

Ш>>2) Если это не баг, то это дыра в стандарте. Срочно фиксить стандарт.
Ш>>3) Пользоваться такими изобретениями в реальной работе категорически нельзя. Ломиком по рукам.

К>Больше всего это похоже на нарушение ODR.


Нет-нет! Подождите!
Где ж тут нарушение ODR? Для какого объявления есть более одного определения???

ODR — это как раз то, с чем пришлось побороться при реализации.
И имхо я его побороол, т.к. у меня получаются просто разные типы. Фактически это равнозначно такому _рукописному_ коду:
magic<0>::val;
magic<1>::val;
magic<2>::val;

Тут очевидно нет никакого нарушения ODR — просто обычный код.

А по поводу того, что написано в аргументе шаблона по-умолчанию — ну так это же аргумент (сравните с параметром)! А аргумент относится к call-side. Т.е. фактически равнозначно:
magic<sizeof(...)>::val;
magic<sizeof(...)>::val;
magic<sizeof(...)>::val;

Тоже никакого нарушения не вижу!




К>
К>// генератор последовательности (любой)
К>template<bla-bla-bla> struct sequence { bla-bla-bla };

К>typedef t1 = sequence<>;
К>typedef t2 = sequence<>;
К>


Нет-нет-нет. Тоже не cогласен.
typdef запоминает конкретный template-id, template он не запоминает. Если аргументы не указаны, значит в template-id используются аргументы по-умолчанию. Всё. Точка.
Тут всё однозначно! Никаких разночтений и вопросов!


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 09.02.07 06:43
Оценка:
Здравствуйте, remark, Вы писали:

Ш>>С чего бы это? У тебя тип параметра не совпадает с типом, в котором продекларирован engine().


и че с того?
если объявление идет в глобально пространство, то все нормально.
если в локальное, то передачу по ссылке в объявлении френда можно заменить на передачу по значению.

R>Отвечаю на конкретный вопрос


R>Похоже тут ты прав.

R>Тогда предлагаю сделать так (тут вроде в этом плане всё чисто):

R>int main()
R>{
R>    char a[magic<>::val != magic<>::val ? 1 : -1];
R>    (void)a;
R>}


на EDG от Dinkum не работает
Re[8]: Невероятно, но факт! Не константные значения в компай
От: Roman Odaisky Украина  
Дата: 09.02.07 09:25
Оценка:
Здравствуйте, remark, Вы писали:

R>участвует в перегрузке наравне со всеми остальными


Или я что-то путаю, или функции, которые находит только ADL, имеют более низкий приоритет?
До последнего не верил в пирамиду Лебедева.
Re[9]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 09.02.07 09:50
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

R>>участвует в перегрузке наравне со всеми остальными


RO>Или я что-то путаю, или функции, которые находит только ADL, имеют более низкий приоритет?


увы
сам офигел когда узнал, но простой поиск и ADL имеют одинаковый приоритет.
то есть сначала происходит поиск имен (все поиски) а потом оверлоад ресолюшн.
так что будте осторожны с выборос жадных перегрузок.
Re[8]: Невероятно, но факт! Не константные значения в компай
От: Lorenzo_LAMAS  
Дата: 09.02.07 10:14
Оценка:
RO>Зависит ли здесь поиск имен от того, чем инстанцируется C? По-моему, очень даже зависит.


Что ты хотел сказать этим примером-то? Например, я инстанцировал C типом int, что ADL тут сработает? Или каким-то еще классом (и при этом инстанцировал C неважно каким типом) что, ADL тут тебе поможет????
Of course, the code must be complete enough to compile and link.
Re[7]: Невероятно, но факт! Не константные значения в компай
От: Lorenzo_LAMAS  
Дата: 09.02.07 10:23
Оценка:
Теперь потрудись объяснить, к чему ты эту цитату привел и как она доказывает корректность поведения вижуала.
Of course, the code must be complete enough to compile and link.
Re[4]: Невероятно, но факт! Не константные значения в компай
От: Кодт Россия  
Дата: 09.02.07 10:44
Оценка: +1
Здравствуйте, remark, Вы писали:

К>>Больше всего это похоже на нарушение ODR.


R>Нет-нет! Подождите!

R>Где ж тут нарушение ODR? Для какого объявления есть более одного определения???

Мда, действительно... значит, не оно.

Хотя ситуация, когда одно и то же выражение в разных частях одного и того же scope резолвится по-разному — настораживает...
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[11]: Невероятно, но факт! Не константные значения в компа
От: Sharp Eye Россия  
Дата: 09.02.07 10:45
Оценка: :)
Здравствуйте, remark, Вы писали:

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


А>>Я думаю, Комо, а скорее всего, последний фронт-энд от едг (у Комо он какой-то древний уже). Уж если ЕДГ и глючит, то в совсем уж нетривиальных моментах.

А>>Автор упомянул ЕДГ, но я не понял, что это значит — купить его простым смертным — малореально

R>EDG C++ это компилирует

R>здесь

R>


EDG C++ это не компилирует:

char a[(magic<>::val != magic<>::val) && (magic<>::val != magic<>::val) ? 1 : -1]; // negative subscript
Re[9]: Невероятно, но факт! Не константные значения в компай
От: Roman Odaisky Украина  
Дата: 09.02.07 11:34
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

RO>>Зависит ли здесь поиск имен от того, чем инстанцируется C? По-моему, очень даже зависит.


L_L>Что ты хотел сказать этим примером-то? Например, я инстанцировал C типом int, что ADL тут сработает? Или каким-то еще классом (и при этом инстанцировал C неважно каким типом) что, ADL тут тебе поможет????


Я не об этом… Если компилятор видит someFunctionDeclaredAsFriend_OrPerhapsNotYet_(someExpr()), то его понимание этого зависит от того, чем инстанцировался класс ранее по ходу и инстанцировался ли вообще. Например:
#if TEST
template <class _>
void doSomething(_ const &)
{
    std::cout << "doNothing" << std::endl;
}
#endif

template <class>
class Friendly;

template <class T>
Friendly<T>& makeFriendly();

doSomething(makeFriendly<int>()); // ?

template <class T>
class Friendly
{
    . . .

    friend void doSomething(Friendly &);
};

doSomething(makeFriendly<int>()); // ?

template <class T>
Friendly<T>& makeFriendly()
{
    return *new Friendly<T>();
}
До последнего не верил в пирамиду Лебедева.
Re[7]: Невероятно, но факт! Не константные значения в компай
От: Lorenzo_LAMAS  
Дата: 09.02.07 11:37
Оценка: 24 (1) +1
Кстати, на случай, если ты не понял, к чему был мой пример — вот еще один:

template<class>
class A
{
   friend void fun(const A<int> &){}
};

int main()
{
   fun(A<int>());
}


Вижуал выдает странные сообщения об ошибках. У комо все как надо, АДЛ работает.
Вот так вот работает и VC

template<class>
class A
{
   friend void fun(const A<int> &){}
};

int main()
{
   A<int>a;
   fun(a);
}


Но это ИМХО говорит лишь о некоторой его кривизне, которую и хочет использовать автор исходного сообщения.
Of course, the code must be complete enough to compile and link.
Re[10]: Невероятно, но факт! Не константные значения в компа
От: Roman Odaisky Украина  
Дата: 09.02.07 11:40
Оценка:
Здравствуйте, 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»)? Хотя тут тоже неясно — причем здесь цласс мембер фунцтион?
До последнего не верил в пирамиду Лебедева.
Re[10]: Тоска без начала. тоска без конца.
От: Lorenzo_LAMAS  
Дата: 09.02.07 11:47
Оценка:
Я поскипал твои примеры, извини, но мне уже влом их смотреть, так же как и тебе, видимо, влом понять, о чем я говорю. Поиск имен, АДЛ _не_ _зависят_ от того, писал ли ты A<someType> строчкой выше до fun(somArg). АДЛ зависит от типа somArg. И используя этот тип АДЛ найдет нужную функцию и без A<someType> строчкой выше. Я говорил об этом. И magic<>::val повторенный сколько угодно раз в этом злосчастном объявлении массива будет одним и тем же. И если у Вижуала это не так — это его проблемы и тех, кто хочет юзать такие трики.
Of course, the code must be complete enough to compile and link.
Re[11]: Невероятно, но факт! Не константные значения в компа
От: night beast СССР  
Дата: 09.02.07 12:08
Оценка:
Здравствуйте, 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);
}
Re: Где VC, gcc и Comeau расходятся во мнениях
От: Roman Odaisky Украина  
Дата: 09.02.07 14:32
Оценка:
Вот здесь:
struct X
{
};

struct Y
{
    friend void testy1(X const &)
    {
    }

    friend void testy0()
    {
    }
};

template <class T>
struct Z
{
    friend void testz1(T const &)
    {
    }

    friend void testz0()
    {
    }
};

int main()
{
    X x;

#if INSTANTIATE

               // g++-3.4.2 VC80 g++-4.1.2 Comeau
    testy1(x); //    OK      OK     --       --
    testy0();  //    OK      --     --       --
    testz1(x); //    --      --     --       --
    testz0();  //    --      --     --       --

#else

    Z<X> instantiate; (void)instantiate;

               // g++-3.4.2 VC80 g++-4.1.2 Comeau
    testy1(x); //    OK      OK     --      --
    testy0();  //    OK      --     --      --
    testz1(x); //    OK      OK     --      --
    testz0();  //    OK      --     --      --

#endif
}

Итак, кто прав?
До последнего не верил в пирамиду Лебедева.
Re[2]: Где VC, gcc и Comeau расходятся во мнениях
От: Lorenzo_LAMAS  
Дата: 09.02.07 14:47
Оценка:
ИМХО.
После того, как здесь не менее 10 раз упомянули, что friend объявление не добавляет имя, которое может найти обычный поиск имен (не АДЛ), странно писать testy1(x) — почему тут что-то должно быть найдено? testy0() а почему тут?
А уж про нахождения имен после инстанцирования старыми версиями gcc и вижуалом — вообще говорить надоело.
Of course, the code must be complete enough to compile and link.
Re[2]: Друзья и ADL
От: Lorenzo_LAMAS  
Дата: 09.02.07 15:01
Оценка:
Так как у тебя нет объявлений функций друзей вне классов, то работать будет только то, что найдет 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.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.