Невероятно, но факт! Не константные значения в компайл-тайм!
От: remark Россия http://www.1024cores.net/
Дата: 06.02.07 20:55
Оценка: 257 (23) -2 :)
Пришло время очередного ресёрча

В компайл-тайм все объекты константные. Будь то интегральные значения или типы. Т.е. имея запись:
const int i = some::val;
typedef some::type type;

всегда some::val будет иметь одно и то же значение и some::type будет одним и тем же типом. В принципе можно к этому добавить входные агрументы:
const int i = some<char, 5>::val;
typedef some<int, 15>::type type;

но результат всё равно всегда однозначно определяется входными значениями. Т.е. это фактически функциональный язык с константными объектами.

Так вот, всё это неправда!
Сейчас вы увидите, как на стандартном с++ можно иметь переменные значения в компайл-тайм!

char engine(...);

template<typename, int> struct magic;
typedef magic<char, -1> magicc;

template<typename type = int, int id = sizeof(engine(*(magicc*)0, *(type*)0))>
struct magic
{
    friend int engine(magicc&, type&);
    static const int val = id;
};

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






Код копилируется gcc4.1/msvc7.1/msvc8.0/edg c++

Вы скажете "Ну и что? Что с помощью этого можно сделать?"
Всё, что можно сделать, я пока не знаю, но знаю, что сделать можно много. Собственно для этого, в частности, я это и публикую, что бы общественность могла придумывать свои применения.

Вот какие применения я на данный момент придумал:

1. Компайл-тайм счётчик. Аналог __COUNTER__, тока лучше. Фичи:
— в любом месте можно завести свой "личный" экземпляр счётчика, т.е. он будет всегда начинать считать с нуля, а не с произвольного меняющегося числа.
— можно генерировать не только последовательность натуральных чисел, а произвольные последовательности: степени 2 (1, 2, 4, 8 ...), чётные числа (0, 2, 4, 6 ...), в сторону уменьшения (0, -1, -2, -3 ...) и т.д.
— если счётчик используется внутри шаблона, будет генерироваться новое значение для каждой специализации шаблона
— можно получить текущее значение счётчика, не инкрементируя его
— типизированный счётчик — выдаёт, например, значения типа short

Примеры использования:

// Просто получаем значение счётчика
int i = cnt<>::val;

// Заводим "личный" счётчик
struct my_tag;
int j = cnt<my_tag>::val;

// Генерируем последовательность степеней двойки
struct my_tag2;
enum x
{
  val1 = cnt<my_tag2, pow2gen>::val,
  val2 = cnt<my_tag2, pow2gen>::val,
  val3 = cnt<my_tag2, pow2gen>::val
};



2. Компайл-тайм генератор случайных чисел.
Никаких особых фич и распределений я не делал. Пример использования:

// Создали массив из 3 случайных чисел от 5 до 20 
int data[] = {rnd<5, 20>::val, rnd<5, 20>::val, rnd<5, 20>::val};



3. ... не знаю как назвать... легче на примере показать. Допустим есть класс:

struct person
{
    prop<person, int> m1;
    prop<person, char> m2;
    prop<person, std::string> m3;
    prop<person, char> m4;
    prop<person, int> m5;
};


Каждый член класса в компайл-тайм получает значение смещения себя относительно объемлющего объекта. Т.е. фактически получается что-то типа следующего:

struct person
{
    prop<person, int, 0> m1;
    prop<person, char, 5> m2;
    prop<person, std::string, 8> m3;
    prop<person, char, 40> m4;
    prop<person, int, 44> m5;
};


Как это работает? Заводится приватный счётчик (cnt<person>). Каждый член получает текущее значение этого счётчика — это есть его смещение. Далее инкрементирует счётчик на свой размер. И уаля. В реальности ещё приходится делать поправку на выравнивание, но это уже детали.
Это даёт возможность членам обращаться к своему контейнеру и наоборот.
Добавляем к этому регистрацию типов (здесь
Автор:
Дата: 26.12.06
или здесь
Автор: Chez
Дата: 28.03.05
) и получаем не больше и не меньше, а compile-time reflection!!!
Для такого класса мы знаем порядок, типы и смещения членов — реализация, например, бинарной сериализации далее видится тривиальной


4. Это переводит
[Trick] Автоматическое определение неиспользуемых заголовков
Автор: remark
Дата: 21.01.07

[Trick] Форсирование правильного использования библиотеки
Автор: remark
Дата: 21.01.07

[Trick] Форсирование проверки возвращаемого значения
Автор: remark
Дата: 24.12.06

из разряда M$ SPECIFIC в 100% PURE C++



Дальше у кого на сколько хватит фантазии
Код указанных фич я приведу в отдельных постах, что бы сюда слишком много не мешать.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Невероятно, но факт! Не константные значения в компайл-т
От: Шахтер Интернет  
Дата: 07.02.07 15:21
Оценка: +7
Здравствуйте, remark, Вы писали:

R>Пришло время очередного ресёрча


Хочу влить свою бочку дегтя в эту ложку сахарного сиропа.

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

2) Если это не баг, то это дыра в стандарте. Срочно фиксить стандарт.

3) Пользоваться такими изобретениями в реальной работе категорически нельзя. Ломиком по рукам.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: Невероятно, но факт! Не константные значения в компайл-т
От: jazzer Россия Skype: enerjazzer
Дата: 08.02.07 14:32
Оценка: +3
Здравствуйте, remark, Вы писали:

R>Пришло время очередного ресёрча


+3 за полет мысли!

P.S. Но мне это категорически не нравится.
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: Ремарки от ремарка :)
От: remark Россия http://www.1024cores.net/
Дата: 14.02.07 20:27
Оценка: +3
Здравствуйте, remark, Вы писали:

R>Пришло время очередного ресёрча


Ну... вобщем я так понял, что... код всё-таки противоречит стандарту
Особенное спасибо Lorenzo_LAMAS и Pavel Chikulaev за разъяснения и настойчивость

Ну, лично для меня, это осталось по крайней мере очень интересным и познавательным...

Тем не менее похоже, что не работает это исключительно на Comeau. И это остаётся рабочим вариантом на msvc71/msvc80/gcc34/gcc41/icc70/icc80/edg. Впечатляет, правда? Не работает только на самых свежих фронт-ендах edg.
Имхо список компиляторов достаточен даже для включения в boost

Вообще это очень странно. msvc, gcc и icc имеют разные ядра, и тем не менее модель компиляции таких шаблонов у них поразительно одинаково неправильная

R>


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: А INTERNAL COMPILER ERROR тоже вызывает ажиотаж?
От: Erop Россия  
Дата: 07.02.07 13:25
Оценка: 27 (1) :)
Здравствуйте, remark, Вы писали:

R>Пришло время очередного ресёрча

Это классно!

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>


Вообще-то, АФАИК это не совсем "на стандартном с++"...
Я так понял, что ты пользуешься дыркой в стандарте. (похожее я писал и тут
Автор: Erop
Дата: 07.02.07
)

Идея в том, что ты хочешь шаблонно заводить нешаблонную функцию в глобальном пространстве имён. Типа так:
template<typename T>
class FriendHack {
    friend foo( T ) { }  //  разве foo -- шаблонная?
};


АФАИК foo -- она не шаблонная. И где она там получается определённой и как и когда появится при поиске кандидатов, при разрешении неоднозначноти вроде никак не гарантируется.

Соответсвенно, если тебе кажется, что это стандартное поведение, то не плохо бы было сделать две вещи

1) Найти где в стандарте описано, как это должно работать.
2) Написать простой пример и проверить работает ли это...

додаток1
Возможный контрольный пример:

void foo( ... ) { cout << "no"; }
template<typename T>wraper { friend foo( T ) { cout << "yes"; }

f1() { foo( 1 ); }
warper<int> q;
f2() { foo( 1 ); }

int main(int, char**)
{
    f1();
    f2();
}


додаток2
За то, что я прав, голосует ещё и то, что даже у M$ не всё так классно. Если бы всё было так, как ты думаешь, то в функции engine вроде как не был бы нужен второй аргумент...


Увы, в этот раз, похоже, опять не получилось
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
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: Невероятно, но факт! Не константные значения в компайл-т
От: Андрей Тарасевич Беларусь  
Дата: 06.02.07 21:39
Оценка: 3 (1) +1
Здравствуйте, remark, Вы писали:

R>Сейчас вы увидите, как на стандартном с++ можно иметь переменные значения в компайл-тайм!


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>


Хм... Оригинально, но не понятно, должно ли это работать так, как задумано. Как известно, friend declaration не вводит в охватывающий namespace видимого имени. Поэтому не ясно, почему в твоем случае при второй инстанциации 'magic' lookup для дефолтного аргумента вдруг должно найти именно "друга", а не явно объявленную оригинальную версию 'engine'...

На Comeau Online — не работает. А именно, оба 'magic<>::val' одинаковы.
Best regards,
Андрей Тарасевич
Re[6]: Невероятно, но факт! Не константные значения в компай
От: Pavel Chikulaev Россия  
Дата: 08.02.07 16:36
Оценка: 2 (2)
Здравствуйте, Lorenzo_LAMAS, Вы писали:

R>>Я серьёзно считаю, что поиск имён зависит от того, что видно в POI.


L_L>Мне вот тоже влом думать Я написал простой пример:

L_L>
L_L>template<class>
L_L>class A
L_L>{
L_L>   friend void fun(const A<char> *);
L_L>};

L_L>int main()
L_L>{
L_L>   A<char> * p = 0;
L_L>   fun(p);
L_L>}
 
L_L>

L_L>Комо находит функцию.
L_L>Вижуал — лошит — не находит! Зато, если я добавляю
L_L>
L_L>int main()
L_L>{
L_L>   A<int>a;
L_L>   A<char> *p = 0;
L_L>   fun(p);
L_L>}
L_L>


L_L>Он уже может найти эту функцию. Так вот ты что, утверждаешь, что такое поведение вижуала правильное???

14.6.5/2
[q]
As with non-template classes, the names of namespace-scope friend functions of a class template specialization
are not visible during an ordinary lookup unless explicitly declared at namespace scope (11.4).
Such names may be found under the rules for associated classes (3.4.2).131) [Example:
template<typename T> class number {
public:
number(int);
//...
friend number gcd(const number& x, const number& y);
//...
void g()
{
number<double> a(3), b(4);
//...
a = gcd(a,b); // finds gcd because number<double> is an
// associated class, making gcd visible
// in its namespace (global scope)
b = gcd(3,4); // ill-formed; gcd is not visible
}
 

—end example]
};
[/q]
Re[2]: Невероятно, но факт! Не константные значения в компай
От: Lorenzo_LAMAS  
Дата: 07.02.07 10:33
Оценка: +2
Здравствуйте, greenya, Вы писали:

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

G>.......
R>>


G>м-да.

G>а я думал я знаю си++

Тут речь идет о специфических глюканах компиляторов, к С++ не имеющих отношения, так что не расстраивайся.
Of course, the code must be complete enough to compile and link.
Re[6]: Невероятно, но факт! Не константные значения в компай
От: Pavel Chikulaev Россия  
Дата: 07.02.07 13:29
Оценка: 24 (1)
Здравствуйте, Erop, Вы писали:

E>ИМХО ты пользуешься дыркой в стандарте, когда ты объявляешь, фактически шаблонную функцию, как нешаблонную.

E>
E>template<typename T>
E>class FriendFake {
E>    friend void foo( T ) {}
E>};
E>


E>Вроде как мы при инстанциировании шаблона FriendFake за одно породили нешаблонную функцию foo.

E>(Почему нешаблонную? Да потому что при её вызове не будет явно или неявно выводится параметры шаблона)
Нет эта функцию имеем еще до инстацирования шаблона. А в VC баг. См. 7.3.1.2/3 или http://rsdn.ru/Forum/Message.aspx?mid=2339364&amp;only=1
Автор: Pavel Chikulaev
Дата: 07.02.07


E>ИМХО поиск и участие таких функций в разрешении неоднозначнойстей при вызове -- нифига в шаблоне не специфицированы и являются особенностью реализации шаблонов в компилятрое
Re[5]: Невероятно, но факт! Не константные значения в компай
От: Erop Россия  
Дата: 07.02.07 13:08
Оценка: 1 (1)
Здравствуйте, night beast, Вы писали:

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

А>>Т.е. поиск имен, по-твоему, зависит от того, сколько ты раз написал magic<> ?
NB>поиск имен зависит от того, какие аргументы принимает функция.
NB>если функия принимает аргументом magic, то поиск подходящей функции будет происходит и в пространстве magic.

Вообще-то говоря у тебя не совсм так написано...
у тебя engine в глобальном пространстве вроде. Это эе друг?
А ещё, кстати, в оюласть поиска имён входит не сам тип аргумента, а пространство, где он был объявлен..

Так что я, например, не понял, от чего это всё должно работать.

И главное. Я так и не смог найти где же подстановка аргументов шаблона либо формирование списка областей где искать, зависит от того, какие шаблоны уже ьыли инстанциированы.

ИМХО ты пользуешься дыркой в стандарте, когда ты объявляешь, фактически шаблонную функцию, как нешаблонную.
template<typename T>
class FriendFake {
    friend void foo( T ) {}
};


Вроде как мы при инстанциировании шаблона FriendFake за одно породили нешаблонную функцию foo.
(Почему нешаблонную? Да потому что при её вызове не будет явно или неявно выводится параметры шаблона)

ИМХО поиск и участие таких функций в разрешении неоднозначнойстей при вызове -- нифига в шаблоне не специфицированы и являются особенностью реализации шаблонов в компилятрое
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 07.02.07 21:41
Оценка: 1 (1)
Здравствуйте, Lorenzo_LAMAS, Вы писали:

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


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

G>>.......
R>>>


G>>м-да.

G>>а я думал я знаю си++

L_L>Тут речь идет о специфических глюканах компиляторов, к С++ не имеющих отношения, так что не расстраивайся.


Можно поподробнее и поаргументированнее.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Друзья и ADL
От: Roman Odaisky Украина  
Дата: 08.02.07 20:45
Оценка: 1 (1)
Давайте определимся. Что из этого должно работать?

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();
}
До последнего не верил в пирамиду Лебедева.
Re[3]: Невероятно, но факт! Не константные значения в компай
От: IROV..  
Дата: 06.02.07 22:40
Оценка: +1
Здравствуйте, remark, Вы писали:

R>Здравствуйте, IROV.., Вы писали:


IRO>>Будь проще и люди подтянутся

R>А зачем они мне?
А в прочем ты прав _люди_ такое не используют


IRO>>А то что только первое и второе вхождение будет, видно из кода, точнее из за механизма!


R>Да, тут я привёл только для двух, что бы было понятнее. Смотри здесь
Автор: remark
Дата: 07.02.07
для полной версии счётчика.


полной?

error C2065: 'lin_gen' : undeclared identifier

я не волшебник, я только учусь!
Re[3]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 07.02.07 07:57
Оценка: +1
Здравствуйте, remark, Вы писали:

АТ>>На Comeau Online — не работает. А именно, оба 'magic<>::val' одинаковы.


R>Да, я знаю... это не ко мне, это к ним


ты им багрепорт отправил?
Re[3]: Невероятно, но факт! Не константные значения в компай
От: Аноним  
Дата: 07.02.07 08:14
Оценка: :)
Т.е. поиск имен, по-твоему, зависит от того, сколько ты раз написал magic<> ?
Или я не так тебя понял?
Re: Невероятно, но факт! Не константные значения в компайл-т
От: Константин Л.  
Дата: 07.02.07 10:14
Оценка: +1
Здравствуйте, 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>


[]

как я понял каждое выражение magic<>::val должно инстанциировать magic заново и sizeof(engine(*(magicc*)0, *(type*)0)) выдавать новые значение?
Все равно не очень понятно
Re[11]: Невероятно, но факт! Не константные значения в компа
От: Аноним  
Дата: 07.02.07 14:14
Оценка: +1
Здравствуйте, night beast, Вы писали:

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


А>>>>Дак это-то понятно, что это особенности компилятора.


NB>>>назови хоть один, который компилит правильно


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


NB>Комо считает, что правильным является char engine(...)

NB>что имхо не правильно.

Хех, для начала надо попытаться обосновать, почему это неправильно
Кстати, как насчет этого:

http://rsdn.ru/Forum/Message.aspx?mid=2338981&amp;only=1
Автор: Шахтер
Дата: 07.02.07
Re[12]: Невероятно, но факт! Не константные значения в компа
От: night beast СССР  
Дата: 07.02.07 14:31
Оценка: :)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, night beast, Вы писали:


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


А>>>>>Дак это-то понятно, что это особенности компилятора.


NB>>>>назови хоть один, который компилит правильно


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


NB>>Комо считает, что правильным является char engine(...)

NB>>что имхо не правильно.

А>Хех, для начала надо попытаться обосновать, почему это неправильно


попробую. поправь если где ошибся
template<typename type = int, int id = sizeof(engine(*(magicc*)0, *(type*)0))>
struct magic
{
    friend int engine(magicc&, type&);
    static const int val = id;
};

magic<>::val ==
magic<int,sizeof(engine(*(magicc*)0, *(type*)>::val ==
*(magicc*) (инстанцирование добавляет функцию magicс::engine) -> magicc::engine(*(magicc*)0, *(type*) -> magic<int,sizeof(int)>
твой ход

А>Кстати, как насчет этого:

А>http://rsdn.ru/Forum/Message.aspx?mid=2338981&amp;only=1
Автор: Шахтер
Дата: 07.02.07


на это могу ответить следующим
http://www.rsdn.ru/Forum/Message.aspx?mid=2339499&amp;only=1
Автор: night beast
Дата: 07.02.07

Re[5]: А INTERNAL COMPILER ERROR тоже вызывает ажиотаж?
От: Erop Россия  
Дата: 07.02.07 17:16
Оценка: +1
Здравствуйте, night beast, Вы писали:

NB>я опираюсь на книгу Вандервуда. но там к сожалению (или к счастью) ссылки на стандарт нет.

Книга хорошая.
Только там не всё понятно как оно должно быть.
Ещё раз повторюсь. Ситауция крайне мутная. Как будут взаимодействовать побочные последствия независимых инстанциаций шаблонов.


E>>А там однохренственно первый аргумент от параметра вроде зависит. Так что всё равно имя зависимое получается и сразу подставляться не должно бы...


NB>не, первый там фиксированый: magic<char,-1>

Упс, точно.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Невероятно, но факт! Не константные значения в компай
От: Roman Odaisky Украина  
Дата: 07.02.07 21:14
Оценка: +1
Здравствуйте, night beast, Вы писали:

NB>
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>>}
NB>


NB>вопрос по выделенному. при замене *(magicc*)0 на magicc() получаем одинаковые magic<>::val.

NB>чем вызвано?

это-то понятно. rvalue не привязывается к неконстантной ссылке. Здесь кошернее всего писать так:
template <class X>
X& make(); // для sizeof сойдет и без тела

. . .

engine(make<magicc>(), make<type>())
До последнего не верил в пирамиду Лебедева.
Re[6]: Невероятно, но факт! Не константные значения в компай
От: Lorenzo_LAMAS  
Дата: 08.02.07 08:35
Оценка: +1
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>Ошибка ни о чём не говорит. Где и что конкретно не так.


Да что ты? Она говорит о том, что magic<>::val он один и не меняется. Или нет?


R>Аааа... ты про это мне хотел сказать???


Не, я хотел о другом — забавно, я вчера пробовал — и он орал о разыменовании нулевых указателей. Похоже, что это он замечает в relaxed mode.

А вообще, так как всем нам, похоже, одинаково некогда/лень ковыряться в стандарте и искать обоснований тех или иных утверждений, лучше подождать авторитетных мнений: Андрея Тарасевича, Павла Кузнецова, elcste (порядок указания имен произвольный ). Можно спросить на comp.lang.c++.moderated.
Лично для меня очевидно, что поиск имен должен работать всегда одинаково и не зависеть от того, что и сколько раз инстанцировалось.
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[5]: Невероятно, но факт! Не константные значения в компай
От: Шахтер Интернет  
Дата: 10.02.07 10:23
Оценка: +1
Здравствуйте, remark, Вы писали:

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


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


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


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

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

Да нет, не будет это работать.

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 


Эта строчка вызовет следующие действия компилятора

1) magic<> -> magic<int,id> . Вычислить id.
2) id = sizeof ( engine(magic_base<int> &,int &) ) . Найти engine.
3) Первый кандидат -- char engine(...).
4) Включаем ADL. Первый аргумент -- magic_base<int> &. Ищем в пространстве имен magic_base<int>. Для этого инстантинируем magic_base<int>.
5) По ADL находим второго кандидата -- int magic_base<int>::engine(magic_base<int> &,int &).
6) Второй кандидат выигрывает по правилам разрешения перегрузки.
7) id=4



      != magic<>::val ? 1 : -1];

Всё повторится с тем же самым результатом (за тем исключением, что второй раз magic_base<int> инстантинирован не будет).


    (void)a;
}



R>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: Для тупых, посните, всё-таки?
От: Erop Россия  
Дата: 10.02.07 10:26
Оценка: +1
Здравствуйте, 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>


Вот смотри. Я так тебя понял что ты ждёшь, что выделенное неравенство будет соблюдено.
Вот и поясни (без всяких там ссылок на тонкости стандарта), как, по твоему мнению обстоит дело.
Где именно и какие именоо инстанциации инстанциируются. То есть укажи пожалуйста место POI для всех участвующих в процессе шаблонов.

А то я что-то никак не въеду
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Ремарки от ремарка :)
От: _nn_  
Дата: 17.02.07 13:50
Оценка: :)
Здравствуйте, remark, Вы писали:

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


R>>Пришло время очередного ресёрча


R>Ну... вобщем я так понял, что... код всё-таки противоречит стандарту

R>Особенное спасибо Lorenzo_LAMAS и Pavel Chikulaev за разъяснения и настойчивость

R>Ну, лично для меня, это осталось по крайней мере очень интересным и познавательным...


R>Тем не менее похоже, что не работает это исключительно на Comeau. И это остаётся рабочим вариантом на msvc71/msvc80/gcc34/gcc41/icc70/icc80/edg. Впечатляет, правда? Не работает только на самых свежих фронт-ендах edg.


VC9 Jan CTP. можно тоже включить в список поддерживаемых багофичу
Только бы к релизу не устранили баг
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Невероятно, но факт! Не константные значения в компайл-т
От: Yoh Asakura  
Дата: 20.06.07 20:49
Оценка: +1
Все что невероятно — заканчивается обычно тем, что сия магия перестает работать на выпущенных позже компиляторах.
Re[2]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 20.06.07 21:01
Оценка: :)
Здравствуйте, Yoh Asakura, Вы писали:

YA>Все что невероятно — заканчивается обычно тем, что сия магия перестает работать на выпущенных позже компиляторах.


Сия магия заканчивается обычно тем, что производителям компиляторов приходится пожизненно поддерживать флаги для обратной совместимости поведения. Даже если это было не стандартное поведение или просто баг.


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

E>Не, ну это ты себе льстишь всё-таки. Хотя хак классный, жалко, что не по стандарту

E>Для того, чтобы производители компилятора поддерживали в следующих версиях багу, как фичу, требуется, чтобы багу начали использовать таки массово

Ну есть немного
А для того, что бы багу исправили в следующей версии компилятора тоже требуется, что бы багу "начали использовать массово". Т.ч. я всё равно не думаю, что М$ будет париться и исправлять *такой* баг, мне даже его субмитить лень.
Вот я один им отправлял здесь, так они ответили:

[бла-бла-бла, мы не будем исправлять баг, т.к] as the code is convoluted and does not reflect the majority of real world use cases


Мой код "свернутый спиралью"


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

T>Дело в том, что раз Comeau работает по стандарту, значит, он должен найти


T>
T>yes flag<int,no,-1>::check(flag<flag_type,no,-1>&,type&);
T>


T>Он там точно есть. Если ADL не должен находить его — то что же вообще он должен находить? Это ведь именно тот же самый тип!


Да, должен найти, только в обеих случаях, а не только во втором.

T>


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: Невероятно, но факт! Не константные значения в компай
От: tilarids Украина tilarids.blogspot.com
Дата: 21.06.07 15:03
Оценка: :)
Здравствуйте, remark, Вы писали:

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


T>>Дело в том, что раз Comeau работает по стандарту, значит, он должен найти


T>>
T>>yes flag<int,no,-1>::check(flag<flag_type,no,-1>&,type&);
T>>


T>>Он там точно есть. Если ADL не должен находить его — то что же вообще он должен находить? Это ведь именно тот же самый тип!


R>Да, должен найти, только в обеих случаях, а не только во втором.


Ну, это стандартом не оговорено, кажется, — что должно происходить вначале — подсчёт дефолтовых параметров, или включение в loookup всех внутренних функций. Если оговорено — цитату, пожалуйста. А то Comeau пока в меньшинстве — мне более логичным на моем примере кажется поведение именно всех остальных компиляторов(точнее, поведение на нем студии )
<вырезано, дабы сохранить место на сервере>
Re: Невероятно, но факт! Не константные значения в компайл-т
От: Roman Odaisky Украина  
Дата: 06.02.07 21:43
Оценка:
Здравствуйте, remark, Вы писали:

R>Пришло время очередного ресёрча


Я попробовал на VC9, только первые 2 значения разные
До последнего не верил в пирамиду Лебедева.
Re: Невероятно, но факт! Не константные значения в компайл-т
От: IROV..  
Дата: 06.02.07 21:57
Оценка:
typedef struct {} _false;
typedef struct {} _true;

char engine( ... );

template<int id = sizeof( engine( _true() ) )>
struct magic
{
    friend int engine(_true);
    static const int val = id;
};

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


Будь проще и люди подтянутся

А то что только первое и второе вхождение будет, видно из кода, точнее из за механизма!

Вся ботва в двух ключевых моментах а именно

char engine( ... ); // выбор данной функции при перегрузке всегда последния (скока можно красивых вещей на этом сделать)

и то что sizeof() не ищет реализацию а только оглавление.

Комеаут скорее всего не работает так как надо, потомучто он не успел найти обявление friend int engine(_true);
я не волшебник, я только учусь!
Re[2]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 06.02.07 22:27
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Хм... Оригинально, но не понятно, должно ли это работать так, как задумано. Как известно, friend declaration не вводит в охватывающий namespace видимого имени. Поэтому не ясно, почему в твоем случае при второй инстанциации 'magic' lookup для дефолтного аргумента вдруг должно найти именно "друга", а не явно объявленную оригинальную версию 'engine'...


Да, friend declaration не вводит в охватывающий namespace видимого имени. Всё правильно. Над этой проблемой пришлось побороться.
На помощь пришёл ADL! Смотри:

class complex
{
  ...
  friend complex operator + (complex, complex);
};

complex c1, c2;
c1 + c2;


Это же работает, хотя тоже вроде как не должно, т.к. operator + () вообще говоря не виден вне класса.

Поэтому я добавил в функцию engine() параметр magic&! Теперь она тоже попадает в рассмотрение!

АТ>На Comeau Online — не работает. А именно, оба 'magic<>::val' одинаковы.


Да, я знаю... это не ко мне, это к ним


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

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


R>>Пришло время очередного ресёрча


RO>Я попробовал на VC9, только первые 2 значения разные


Во-первых, это уже круто!
Во-вторых, что такое VC9
В-третих, Да, всё правильно, тут я только для двух сделал, что бы было хоть чуть-чуть понятно как работает

Смотри здесь
Автор: remark
Дата: 07.02.07
. Там можно много значений.


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

IRO>Будь проще и люди подтянутся

А зачем они мне?

IRO>А то что только первое и второе вхождение будет, видно из кода, точнее из за механизма!


Да, тут я привёл только для двух, что бы было понятнее. Смотри здесь
Автор: remark
Дата: 07.02.07
для полной версии счётчика.

IRO>Вся ботва в двух ключевых моментах а именно


IRO>char engine( ... ); // выбор данной функции при перегрузке всегда последния (скока можно красивых вещей на этом сделать)


Не понял, что имеется в виду...
Да, engine(...), имеет наименьший приоритет при выборе перегрузок, на этом всё и построено...

IRO>и то что sizeof() не ищет реализацию а только оглавление.


Опять не понял...

IRO>Комеаут скорее всего не работает так как надо, потомучто он не успел найти обявление friend int engine(_true);


Да, Комеаут не работает, я знаю, но это не ко мне, а к нему


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

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


R>>Здравствуйте, IROV.., Вы писали:


IRO>>>Будь проще и люди подтянутся

R>>А зачем они мне?
IRO>А в прочем ты прав _люди_ такое не используют
Я никого не принуждаю это использовать, и даже читать не принуждаю...


IRO>>>А то что только первое и второе вхождение будет, видно из кода, точнее из за механизма!


R>>Да, тут я привёл только для двух, что бы было понятнее. Смотри здесь
Автор: remark
Дата: 07.02.07
для полной версии счётчика.


IRO>полной?

IRO>

error C2065: 'lin_gen' : undeclared identifier


А ты скопировал определение lin_gen?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Невероятно, но факт! Не константные значения в компайл-т
От: np9mi7 Россия  
Дата: 07.02.07 09:47
Оценка:
Здравствуйте, remark, Вы писали:

R>3. ... не знаю как назвать... легче на примере показать. Допустим есть класс:


R>В реальности ещё приходится делать поправку на выравнивание, но это уже детали.


Каким образом делается поправка на выравнивание?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Re[4]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 07.02.07 10:02
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Т.е. поиск имен, по-твоему, зависит от того, сколько ты раз написал magic<> ?


поиск имен зависит от того, какие аргументы принимает функция.
если функия принимает аргументом magic, то поиск подходящей функции будет происходит и в пространстве magic.

до инстанцирования magic<-1> есть только engine(...);
после добавляется engine(magic<-1>);

А>Или я не так тебя понял?


похоже на то.
Re[5]: Невероятно, но факт! Не константные значения в компай
От: Аноним  
Дата: 07.02.07 10:12
Оценка:
Здравствуйте, night beast, Вы писали:

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


А>>Т.е. поиск имен, по-твоему, зависит от того, сколько ты раз написал magic<> ?


NB>поиск имен зависит от того, какие аргументы принимает функция.

NB>если функия принимает аргументом magic, то поиск подходящей функции будет происходит и в пространстве magic.

NB>до инстанцирования magic<-1> есть только engine(...);

NB>после добавляется engine(magic<-1>);

А ты не думал, что поиск имен не зависит от инстанцирования и вещи это ортогональные?

А>>Или я не так тебя понял?


NB>похоже на то.

Ну так поясни, почему похоже. Т.е. по твоим представлениям, С++ это язык в котором

void fun()
{
name;
name;
}

поиск имени name зависит от того, в какой оно строке стоит?
Re: Невероятно, но факт! Не константные значения в компайл-т
От: greenya Украина  
Дата: 07.02.07 10:26
Оценка:
Здравствуйте, remark, Вы писали:
.......
R>


м-да.
а я думал я знаю си++
Re: Невероятно, но факт! Не константные значения в компайл-т
От: Pavel Chikulaev Россия  
Дата: 07.02.07 10:53
Оценка:
Здравствуйте, remark, Вы писали:

[snipped]

Смотри ветку http://rsdn.ru/Forum/?mid=1653980&amp;flat=0
Автор: Pavel Chikulaev
Дата: 01.02.06
Re[3]: Невероятно, но факт! Не константные значения в компай
От: Шахтер Интернет  
Дата: 07.02.07 11:05
Оценка:
Здравствуйте, remark, Вы писали:

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


АТ>>Хм... Оригинально, но не понятно, должно ли это работать так, как задумано. Как известно, friend declaration не вводит в охватывающий namespace видимого имени. Поэтому не ясно, почему в твоем случае при второй инстанциации 'magic' lookup для дефолтного аргумента вдруг должно найти именно "друга", а не явно объявленную оригинальную версию 'engine'...


R>Да, friend declaration не вводит в охватывающий namespace видимого имени. Всё правильно. Над этой проблемой пришлось побороться.

R>На помощь пришёл ADL! Смотри:

R>
R>class complex
R>{
R>  ...
R>  friend complex operator + (complex, complex);
R>};

R>complex c1, c2;
R>c1 + c2;
R>


R>Это же работает, хотя тоже вроде как не должно, т.к. operator + () вообще говоря не виден вне класса.


R>Поэтому я добавил в функцию engine() параметр magic&! Теперь она тоже попадает в рассмотрение!


С чего бы это? У тебя тип параметра не совпадает с типом, в котором продекларирован engine().
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: Невероятно, но факт! Не константные значения в компай
От: Roman Odaisky Украина  
Дата: 07.02.07 11:47
Оценка:
Здравствуйте, remark, Вы писали:

RO>>Я попробовал на VC9, только первые 2 значения разные


R>Во-вторых, что такое VC9


sorry, VC8
До последнего не верил в пирамиду Лебедева.
Re[6]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 07.02.07 12:15
Оценка:
Здравствуйте, Аноним, Вы писали:

NB>>до инстанцирования magic<-1> есть только engine(...);

NB>>после добавляется engine(magic<-1>);

А>А ты не думал, что поиск имен не зависит от инстанцирования и вещи это ортогональные?



похоже у моего любимого компилятора на этот счет есть свое мнение
Re[7]: Невероятно, но факт! Не константные значения в компай
От: Аноним  
Дата: 07.02.07 12:31
Оценка:
Здравствуйте, night beast, Вы писали:

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


NB>>>до инстанцирования magic<-1> есть только engine(...);

NB>>>после добавляется engine(magic<-1>);

А>>А ты не думал, что поиск имен не зависит от инстанцирования и вещи это ортогональные?


NB>

NB>похоже у моего любимого компилятора на этот счет есть свое мнение

Дак это-то понятно, что это особенности компилятора.
Re[8]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 07.02.07 12:39
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>>А ты не думал, что поиск имен не зависит от инстанцирования и вещи это ортогональные?


NB>>

NB>>похоже у моего любимого компилятора на этот счет есть свое мнение

А>Дак это-то понятно, что это особенности компилятора.


назови хоть один, который компилит правильно
Re[7]: Будь твёрд в своей любви!
От: Erop Россия  
Дата: 07.02.07 13:09
Оценка:
Здравствуйте, night beast, Вы писали:

NB>

NB>похоже у моего любимого компилятора на этот счет есть свое мнение

Будь твёрд в своей любви!
Это соркк особенности обсуждаемого кода!

В целом хотелось бы узнать почему автору кажется, что это чмстый и стандартный C++...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 07.02.07 13:19
Оценка:
Здравствуйте, Erop, Вы писали:

E>Вообще-то говоря у тебя не совсм так написано...

E>у тебя engine в глобальном пространстве вроде. Это эе друг?
E>А ещё, кстати, в оюласть поиска имён входит не сам тип аргумента, а пространство, где он был объявлен..

э... ты меня ни с кем не перепутал?
Re[8]: Будь твёрд в своей любви!
От: Lorenzo_LAMAS  
Дата: 07.02.07 13:23
Оценка:
E>В целом хотелось бы узнать почему автору кажется, что это чмстый и стандартный C++...

Ну, он этого вроде и не утверждал.
Of course, the code must be complete enough to compile and link.
Re[9]: Будь твёрд в своей любви!
От: Lorenzo_LAMAS  
Дата: 07.02.07 13:24
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

E>>В целом хотелось бы узнать почему автору кажется, что это чмстый и стандартный C++...


L_L>Ну, он этого вроде и не утверждал.

Аааа, утверждал, я разглядел теперь.

Не нравятся мне подобные кошмарики на С++
Of course, the code must be complete enough to compile and link.
Re[6]: Невероятно, но факт! Не константные значения в компай
От: Lorenzo_LAMAS  
Дата: 07.02.07 13:25
Оценка:
E>И главное. Я так и не смог найти где же подстановка аргументов шаблона либо формирование списка областей где искать, зависит от того, какие шаблоны уже ьыли инстанциированы.

+1.
Of course, the code must be complete enough to compile and link.
Re: Невероятно, но факт! Не константные значения в компайл-т
От: Pavel Chikulaev Россия  
Дата: 07.02.07 13:26
Оценка:
Здравствуйте, remark, Вы писали:

R>Сейчас вы увидите, как на стандартном с++ можно иметь переменные значения в компайл-тайм!

Это не стандартный C++

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. [Example:

// Assume f and g have not yet been defined.
void h(int);
template <class T> void f2(T);
namespace A {
class X {
friend void f(X); // A::f(X) is a friend
class Y {
friend void g(); // A::g is a friend
friend void h(int); // A::h is a friend
// ::h not considered
friend void f2<>(int); // ::f2<>(int) is a friend
};
};
// A::f, A::g and A::h are not visible here
X x;
void g() { f(x); } // definition of A::g
void f(X) { /* ... */} // definition of A::f
void h(int) { /* ... */ } // definition of A::h
// A::f, A::g and A::h are visible here and known to be friends
}

Re[10]: Будь твёрд в своей любви!
От: Erop Россия  
Дата: 07.02.07 13:27
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Не нравятся мне подобные кошмарики на С++

Не парься!
Это не C++, а просто дырка в стандарте.
Кажется давно уже известная, кстати
Через неё любят хачить убогость шаблонов шестой студии, например
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Невероятно, но факт! Не константные значения в компай
От: Аноним  
Дата: 07.02.07 13:39
Оценка:
Здравствуйте, night beast, Вы писали:

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


А>>>>А ты не думал, что поиск имен не зависит от инстанцирования и вещи это ортогональные?


NB>>>

NB>>>похоже у моего любимого компилятора на этот счет есть свое мнение

А>>Дак это-то понятно, что это особенности компилятора.


NB>назови хоть один, который компилит правильно


Я думаю, Комо, а скорее всего, последний фронт-энд от едг (у Комо он какой-то древний уже). Уж если ЕДГ и глючит, то в совсем уж нетривиальных моментах.
Автор упомянул ЕДГ, но я не понял, что это значит — купить его простым смертным — малореально
Re[10]: Невероятно, но факт! Не константные значения в компа
От: night beast СССР  
Дата: 07.02.07 13:52
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>>Дак это-то понятно, что это особенности компилятора.


NB>>назови хоть один, который компилит правильно


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


Комо считает, что правильным является char engine(...)
что имхо не правильно.
Re[6]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 07.02.07 14:08
Оценка:
Здравствуйте, Erop, Вы писали:

E>ИМХО ты пользуешься дыркой в стандарте, когда ты объявляешь, фактически шаблонную функцию, как нешаблонную.

E>template<typename T>
E>class FriendFake {
E>    friend void foo( T ) {}
E>};


у remark используется другая декларация
E>template<typename T>
E>class FriendFake {
E>    friend void foo( FriendFake<int>, T ) {}
E>};


реально она нужна только для типа FriendFake<int>.
извне она не видна, но из-за ADL ее можно вызвать.

E>ИМХО поиск и участие таких функций в разрешении неоднозначнойстей при вызове -- нифига в шаблоне не специфицированы и являются особенностью реализации шаблонов в компилятрое


а вот и нет
подробнее C++ Templates: The Complete Guide (11.7 The Barton-Nackman Trick)
Re[7]: Невероятно, но факт! Не константные значения в компай
От: Erop Россия  
Дата: 07.02.07 14:26
Оценка:
Здравствуйте, night beast, Вы писали:

NB>
E>>template<typename T>
E>>class FriendFake {
E>>    friend void foo( FriendFake<int>, T ) {}
E>>};
NB>


NB>реально она нужна только для типа FriendFake<int>.

NB>извне она не видна, но из-за ADL ее можно вызвать.

Да вот и нет!
Вот скажи, декларация
void foo( FriendFake<int>, FriendFake<float> );

Объявляет шаблон функции разве?

А ведь декларации
class CFoo {
    friend void foo( int, float );
};

void foo( int, float );

вроде как равнозначны. Обе вводят в глобальное пространство имён нешаблонную функцию void foo( int, float )
Так что он вполне объявляет глобальную нешаблонную функцию с параметрами зависящими от того, в какой именно инстанциации шаблона класса она введена.

Как влияют эти функции напоиск кандидатов при разрешении неоднозначностей --


E>>ИМХО поиск и участие таких функций в разрешении неоднозначнойстей при вызове -- нифига в шаблоне не специфицированы и являются особенностью реализации шаблонов в компилятрое

NB>а вот и нет
NB>подробнее C++ Templates: The Complete Guide (11.7 The Barton-Nackman Trick)
The Barton-Nackman Trick -- то как раз известный. Кто бы спорил.
Но там где объхявляют, там и используют. А тут какие-то одни инстанциации, должны использовать какие-то другие инстанциации. Вроде как никто ничего про это не обещает.
Я вот, что-то не нашёл в стандарте сразу. Не стразу искать лень, так как мне кажется, что и не найду.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 07.02.07 14:43
Оценка:
Здравствуйте, Erop, Вы писали:

NB>>реально она нужна только для типа FriendFake<int>.

NB>>извне она не видна, но из-за ADL ее можно вызвать.

E>Да вот и нет!

E>Вот скажи, декларация
E>
void foo( FriendFake<int>, FriendFake<float> );

E>Объявляет шаблон функции разве?

вот здесь я не совсем понял вопроса

E>А ведь декларации

E>
E>class CFoo {
E>    friend void foo( int, float );
E>};

E>void foo( int, float );
E>

E>вроде как равнозначны. Обе вводят в глобальное пространство имён нешаблонную функцию void foo( int, float )

E>Так что он вполне объявляет глобальную нешаблонную функцию с параметрами зависящими от того, в какой именно инстанциации шаблона класса она введена.


да. здесь идет декларация глобальной функции.
но если ты во френде задашь и тело, то она уже будет принадлежать только тому классу, в котором появилась.

E>Как влияют эти функции напоиск кандидатов при разрешении неоднозначностей --


E>>>ИМХО поиск и участие таких функций в разрешении неоднозначнойстей при вызове -- нифига в шаблоне не специфицированы и являются особенностью реализации шаблонов в компилятрое

NB>>а вот и нет
NB>>подробнее C++ Templates: The Complete Guide (11.7 The Barton-Nackman Trick)
E>The Barton-Nackman Trick -- то как раз известный. Кто бы спорил.
E>Но там где объхявляют, там и используют. А тут какие-то одни инстанциации, должны использовать какие-то другие инстанциации. Вроде как никто ничего про это не обещает.

ну сэкономил человек на объявлении, что вы привязались.
суть то не в этом.
Re[9]: Невероятно, но факт! Не константные значения в компай
От: Erop Россия  
Дата: 07.02.07 14:47
Оценка:
Здравствуйте, night beast, Вы писали:

NB>ну сэкономил человек на объявлении, что вы привязались.

NB>суть то не в этом.


Э-э-э где и на чём съкономил?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Невероятно, но факт! Не константные значения в компайл-т
От: Tonal- Россия www.promsoft.ru
Дата: 07.02.07 15:31
Оценка:
g++ (GCC) 3.4.5 (mingw special)
Нет обещанного чуда:
C:\tect>g++ -Wall -o "mag" "mag.cpp"
mag.cpp:13: warning: friend declaration `int engine(magicc&, type&)' declares a non-template function
mag.cpp:13: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
mag.cpp: In function `int main()':
mag.cpp:21: warning: unused variable 'a'
Re[10]: Невероятно, но факт! Не константные значения в компа
От: night beast СССР  
Дата: 07.02.07 16:12
Оценка:
Здравствуйте, Erop, Вы писали:

NB>>ну сэкономил человек на объявлении, что вы привязались.

NB>>суть то не в этом.

E>Э-э-э где


friend int engine(magicc&, type&);


E>и на чём съкономил?


на { return 0; }
Re[2]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 07.02.07 16:14
Оценка:
Здравствуйте, Tonal-, Вы писали:

T>g++ (GCC) 3.4.5 (mingw special)

T>Нет обещанного чуда:

добавь
   friend int engine(magicc&, type&) { return 0; }
Re[2]: А INTERNAL COMPILER ERROR тоже вызывает ажиотаж?
От: night beast СССР  
Дата: 07.02.07 16:27
Оценка:
Здравствуйте, Erop, Вы писали:

E>
додаток1

E>Возможный контрольный пример:

E>void foo( ... ) { cout << "no"; }
E>template<typename T>wraper { friend foo( T ) { cout << "yes"; }

E>f1() { foo( 1 ); }
E>warper<int> q;
E>f2() { foo( 1 ); }

E>int main(int, char**)
E>{
E>    f1();
E>    f2();
E>}


если не обращать внимание на синтаксические ляпы, то какое поведение ожидается?
гсс 3.4 выводит noyes, что на мой взгляд некорректно.

E>
додаток2

E>За то, что я прав, голосует ещё и то, что даже у M$ не всё так классно. Если бы всё было так, как ты думаешь, то в функции engine вроде как не был бы нужен второй аргумент...

если я правильно понимаю, второй аргумент нужен чтобы сделать вызов функии engine зависящим от параменра шаблона. это должно предотвратить подстановку функии сразу при обявлении.
Re[11]: Невероятно, но факт! Не константные значения в компа
От: Erop Россия  
Дата: 07.02.07 16:33
Оценка:
Здравствуйте, night beast, Вы писали:

NB>>>ну сэкономил человек на объявлении, что вы привязались.


NB>
NB>friend int engine(magicc&, type&);
NB>


NB>на { return 0; }


Наверное речь шла об определнии?

Но в целом, ИМХО, это всё не важно, так как реальных вызовов функции engine нет, так что и тел нигде не останется.
А то, что "друг с телом" попадёт только вместе с объемлещим классом, то там же как раз аргумент вроде как второй для того есть.
Так что тело вроде не должно бы было помешать
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: А INTERNAL COMPILER ERROR тоже вызывает ажиотаж?
От: Erop Россия  
Дата: 07.02.07 16:36
Оценка:
Здравствуйте, night beast, Вы писали:

NB>гсс 3.4 выводит noyes, что на мой взгляд некорректно.

Я думаю, что это дырка в стандарте. Может быть как угодно

Хотя может если полистать повнимательнее, то этот случае где-то в стандарте расталкован явно. Просто я быстро не нашёл, а долго искать не стал.

NB>если я правильно понимаю, второй аргумент нужен чтобы сделать вызов функии engine зависящим от параменра шаблона. это должно предотвратить подстановку функии сразу при обявлении.


А там однохренственно первый аргумент от параметра вроде зависит. Так что всё равно имя зависимое получается и сразу подставляться не должно бы...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: А INTERNAL COMPILER ERROR тоже вызывает ажиотаж?
От: night beast СССР  
Дата: 07.02.07 17:07
Оценка:
Здравствуйте, Erop, Вы писали:

NB>>гсс 3.4 выводит noyes, что на мой взгляд некорректно.

E>Я думаю, что это дырка в стандарте. Может быть как угодно

E>Хотя может если полистать повнимательнее, то этот случае где-то в стандарте расталкован явно. Просто я быстро не нашёл, а долго искать не стал.


я опираюсь на книгу Вандервуда. но там к сожалению (или к счастью) ссылки на стандарт нет.

NB>>если я правильно понимаю, второй аргумент нужен чтобы сделать вызов функии engine зависящим от параменра шаблона. это должно предотвратить подстановку функии сразу при обявлении.


E>А там однохренственно первый аргумент от параметра вроде зависит. Так что всё равно имя зависимое получается и сразу подставляться не должно бы...


не, первый там фиксированый: magic<char,-1>
Re[12]: Невероятно, но факт! Не константные значения в компа
От: night beast СССР  
Дата: 07.02.07 17:14
Оценка:
Здравствуйте, Erop, Вы писали:

NB>>>>ну сэкономил человек на объявлении, что вы привязались.


NB>>
NB>>friend int engine(magicc&, type&);
NB>>


NB>>на { return 0; }


E>Наверное речь шла об определнии?


да, именно. совсем заврался

E>Но в целом, ИМХО, это всё не важно, так как реальных вызовов функции engine нет, так что и тел нигде не останется.

E>А то, что "друг с телом" попадёт только вместе с объемлещим классом, то там же как раз аргумент вроде как второй для того есть.
E>Так что тело вроде не должно бы было помешать

без тела оно считается вроде как глобальным а здесь
Автор: Pavel Chikulaev
Дата: 07.02.07

Pavel Chikulaev говорит что нельзя.

вобщем, дело темное.
Re: Невероятно, но факт! Не константные значения в компайл-т
От: night beast СССР  
Дата: 07.02.07 17:57
Оценка:
Здравствуйте, remark, Вы писали:

R>Так вот, всё это неправда!

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>}


вопрос по выделенному. при замене *(magicc*)0 на magicc() получаем одинаковые magic<>::val.
чем вызвано?
ну и в magic<char,-1>::engine второй аргумент char.
Re[10]: Невероятно, но факт! Не константные значения в компа
От: remark Россия http://www.1024cores.net/
Дата: 07.02.07 20:57
Оценка:
Здравствуйте, Аноним, Вы писали:

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

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

EDG C++ это компилирует
здесь


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: Будь твёрд в своей любви!
От: remark Россия http://www.1024cores.net/
Дата: 07.02.07 21:02
Оценка:
Здравствуйте, Erop, Вы писали:

E>В целом хотелось бы узнать почему автору кажется, что это чмстый и стандартный C++...


А почему нет?
Априори (без ссылок на стандарт) компилирование 3 самыми популярными и приближенными к стандарту компиляторами чего-то да стоит. По крайней мере того, что бы оппонент представил хотя бы какие-то факты, а не просто фразы, что это типа какая-то там некая давно известная дыра где-то


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

E>И главное. Я так и не смог найти где же подстановка аргументов шаблона либо формирование списка областей где искать, зависит от того, какие шаблоны уже ьыли инстанциированы.


Ну а какие варианты могут быть?
У меня один вариант — зависимые аргументы шаблона по-умолчанию вычисляются в точке инстанциирования. И соответственно на это вычисление влияет всё, что видно в этой точке. К тому же по аналогии с аргументами функции по-умолчанию.
У тебя есть ещё какие-то разумные варианты?


E>ИМХО ты пользуешься дыркой в стандарте, когда ты объявляешь, фактически шаблонную функцию, как нешаблонную.


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


E>
E>template<typename T>
E>class FriendFake {
E>    friend void foo( T ) {}
E>};
E>


E>Вроде как мы при инстанциировании шаблона FriendFake за одно породили нешаблонную функцию foo.

E>(Почему нешаблонную? Да потому что при её вызове не будет явно или неявно выводится параметры шаблона)

Да, так всё и есть. Никаких проблем я не вижу.

E>ИМХО поиск и участие таких функций в разрешении неоднозначнойстей при вызове -- нифига в шаблоне не специфицированы и являются особенностью реализации шаблонов в компилятрое


При разрешении перегрузки участвуют все видимые функции. Понятия "таких" функций в стандарте вообще нет, там есть просто функции.



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

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


R>>Сейчас вы увидите, как на стандартном с++ можно иметь переменные значения в компайл-тайм!

PC>Это не стандартный C++
PC>[q]
PC>7.3.1.2/3

PC>Every name first declared in a namespace is a member of that namespace. If a friend declaration in a

PC>non-local class first declares a class or function the friend class or function is a member of the innermost
PC>enclosing namespace.
The name of the friend is not found by simple name lookup until a matching declaration
PC>is provided in that namespace scope (either before or after the class declaration granting friendship). If
PC>a friend function is called, its name may be found by the name lookup that considers functions from namespaces
PC>and classes associated with the types of the function arguments
(3.4.2). When looking for a prior
PC>declaration of a class or a function declared as a friend, and when the name of the friend class or
PC>function is neither a qualified name nor a template-id, scopes outside the innermost enclosing namespace
PC>scope are not considered. [Example:

Не понял мысль.
По-моему, эта цитата подтверждает работоспособность моего кода.
Да, я объявляю все дружественные функции в глобальном пространстве имён. Всё правильно.
Да, потом я её нахожу, т.к. тип параметра функции есть сам этот класс (если быть совсем точным, то не сам этот класс, а другая специализация этого же шаблона, но касательно областей видимости имён это ничего не меняет).


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

E>Да вот и нет!

E>Вот скажи, декларация
E>
void foo( FriendFake<int>, FriendFake<float> );

E>Объявляет шаблон функции разве?

Что ты привязался к шаблонам функции? Да, я их не объявлял и не собирался объявлять. И это ни о чём не говорит. Это никак не влияет на работоспособность кода.


E>А ведь декларации

E>
E>class CFoo {
E>    friend void foo( int, float );
E>};

E>void foo( int, float );
E>

E>вроде как равнозначны. Обе вводят в глобальное пространство имён нешаблонную функцию void foo( int, float )
E>Так что он вполне объявляет глобальную нешаблонную функцию с параметрами зависящими от того, в какой именно инстанциации шаблона класса она введена.

Да, всё так и есть. В чём проблема?


E>Как влияют эти функции напоиск кандидатов при разрешении неоднозначностей --


Так же как и всё остальные.
Нет понятия каких-то "других" функций, есть просто функции и они все равнозначны и одинакого влияют на разрешение перегрузки.




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

NB>без тела оно считается вроде как глобальным а здесь
Автор: Pavel Chikulaev
Дата: 07.02.07

NB>Pavel Chikulaev говорит что нельзя.

Да, функция объявляется в глобальном пространстве имён. Но я не вижу тут никаких проблем. К сожалению он ничего не пояснил, что хотел сказать...



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

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


R>>3. ... не знаю как назвать... легче на примере показать. Допустим есть класс:


R>>В реальности ещё приходится делать поправку на выравнивание, но это уже детали.


N>Каким образом делается поправка на выравнивание?


Если сегодня успею, то запостю код...


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

КЛ>как я понял каждое выражение magic<>::val должно инстанциировать magic заново и sizeof(engine(*(magicc*)0, *(type*)0)) выдавать новые значение?

КЛ>Все равно не очень понятно

Если на пальцах, то примерно так:

При каждом упоминании magic<>::val заного вычисляется значение аргумента по-умолчанию, причём вычисляется оно именно в той точке, где написано magic<>::val.
И выдаёт это вычисление разные результаты, т.к. предыдущая специализация magic внесла новую перегрузку функции engine.
Как-то так...



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

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


PC>[snipped]


PC>Смотри ветку http://rsdn.ru/Forum/?mid=1653980&amp;flat=0
Автор: Pavel Chikulaev
Дата: 01.02.06


... да действительно всё уже украдено до нас... но Chez явно не разглядел потенциал фичи.


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

NB>>вопрос по выделенному. при замене *(magicc*)0 на magicc() получаем одинаковые magic<>::val.

NB>>чем вызвано?

RO>это-то понятно. rvalue не привязывается к неконстантной ссылке. Здесь кошернее всего писать так:


да, так понятней.
в принципе, второй параметр не нужен:
template<typename type = int, int id = sizeof( engine( make< magic<type,-1> >() ) ) >
struct magic {
    friend int engine( magic<type,-1> );
    static const int val = id;
};
Re[3]: Невероятно, но факт! Не константные значения в компай
От: Pavel Chikulaev Россия  
Дата: 08.02.07 07:26
Оценка:
Здравствуйте, remark, Вы писали:

R>Не понял мысль.

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

R>


Объясню на примере IROVа http://rsdn.ru/Forum/Message.aspx?mid=2338001&amp;only=1
Автор: IROV..
Дата: 07.02.07

typedef struct {} _false;
typedef struct {} _true;

char engine( ... );

template<int id = sizeof( engine( _true() ) )>
struct magic
{
    friend int engine(_true);
    static const int val = id; //*
};

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

friend int engine(_true); в magic<int> объявляет функцию в глобальном пространстве еще до инстанирования шаблона согласно 7.3.1.2/3, поэтому код абсолютно равнозначен этому:
typedef struct {} _false;
typedef struct {} _true;

char engine( ... );
int  engine(_true);

template<int id = sizeof( engine( _true() ) )>
struct magic
{
    static const int val = id; //*
};

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

Именно поэтому на комо это не работает. В VC же баг, там он действительно добавляется лишь после инстанцирования.
Re[2]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 08.02.07 07:38
Оценка:
Здравствуйте, Шахтер, Вы писали:

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


R>>Пришло время очередного ресёрча


Ш>Хочу влить свою бочку дегтя в эту ложку сахарного сиропа.


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


Какие моменты у тебя вызывают недоверие?

Ш>2) Если это не баг, то это дыра в стандарте. Срочно фиксить стандарт.


Почему?

Ш>3) Пользоваться такими изобретениями в реальной работе категорически нельзя. Ломиком по рукам.


С такими тезисами обращайся в Философию, там можно такое обсудить на пару сотен постов Или лучше сразу в холивары Покрайней мере к С++ это отношения не имеет.


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

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


R>>Так вот, всё это неправда!

R>>Сейчас вы увидите, как на стандартном с++ можно иметь переменные значения в компайл-тайм!

NB>
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>>}
NB>


NB>вопрос по выделенному. при замене *(magicc*)0 на magicc() получаем одинаковые magic<>::val.

NB>чем вызвано?

Чем компилил? Это вообще не должно компилироваться, т.к. ты пытаешься сделать вызов конструктора до определения класса. Там, где ты написал magicc() видно только форвард объявление класса...


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

T>g++ (GCC) 3.4.5 (mingw special)

T>Нет обещанного чуда:
T>
T>C:\tect>g++ -Wall -o "mag" "mag.cpp"
T>mag.cpp:13: warning: friend declaration `int engine(magicc&, type&)' declares a non-template function
T>mag.cpp:13: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
T>mag.cpp: In function `int main()':
T>mag.cpp:21: warning: unused variable 'a'
T>


Что ты имеешь в виду?
Да, gcc выдал пару вполне законных варнингов, но они не то что бы особо принципиальные. Если они тебе сильно мешают — можешь их пофиксить...



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

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


R>>Не понял мысль.

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

R>>


PC>Объясню на примере IROVа http://rsdn.ru/Forum/Message.aspx?mid=2338001&amp;only=1
Автор: IROV..
Дата: 07.02.07

PC>
PC>typedef struct {} _false;
PC>typedef struct {} _true;

PC>char engine( ... );

PC>template<int id = sizeof( engine( _true() ) )>
PC>struct magic
PC>{
PC>    friend int engine(_true);
PC>    static const int val = id; //*
PC>};

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


Во-первых, тут ошибка, т.к. friend engine() не должна находится без ADL, т.е. это бы при любом раскладе не стало бы работать. Но это так мелочи.

PC>friend int engine(_true); в magic<int> объявляет функцию в глобальном пространстве еще до инстанирования шаблона согласно 7.3.1.2/3, поэтому код абсолютно равнозначен этому:

PC>
PC>typedef struct {} _false;
PC>typedef struct {} _true;

PC>char engine( ... );
PC>int  engine(_true);

PC>template<int id = sizeof( engine( _true() ) )>
PC>struct magic
PC>{
PC>    static const int val = id; //*
PC>};

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


Нет, это абсолютно не равнозначно.

PC>Именно поэтому на комо это не работает. В VC же баг, там он действительно добавляется лишь после инстанцирования.


Подсказка 1.

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


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

Подсказка 2.

Подумай о POI. Когда в первый раз компилятор начинает компилировать специализацию шаблона. И когда он действительно видет, что какую-то функцию надо выносить в глобальное пространство, и видит какую именно. До POI, т.е. пока не требуется определения класса, компилятор не то что не обязан, он не может компилировать специализацию.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Невероятно, но факт! Не константные значения в компай
От: Sm0ke Россия ksi
Дата: 08.02.07 07:56
Оценка:
А почему не зделать так?:
template<typename type = int, int id = sizeof( engine( new magic<type,-1> ) ) >
struct magic {
    friend int engine( magic<type,-1> * );
    static const int val = id;
};
Re[3]: Невероятно, но факт! Не константные значения в компай
От: Аноним  
Дата: 08.02.07 08:11
Оценка:
Здравствуйте, remark, Вы писали:

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


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


R>>>Пришло время очередного ресёрча


Ш>>Хочу влить свою бочку дегтя в эту ложку сахарного сиропа.


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


R>Какие моменты у тебя вызывают недоверие?



Для начала — разыменование нулевого указателя.

R>Почему?


Ты что, серьезно считаешь, что поиск имен зависит от того, что было инстанцировано, а что нет?

Ш>>3) Пользоваться такими изобретениями в реальной работе категорически нельзя. Ломиком по рукам.


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


Код с UB уже тоже.
Re[5]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 08.02.07 08:11
Оценка:
Здравствуйте, Sm0ke, Вы писали:

S>А почему не зделать так?:

S>
S>template<typename type = int, int id = sizeof( engine( new magic<type,-1> ) ) >
S>struct magic {
S>    friend int engine( magic<type,-1> * );
S>    static const int val = id;
S>};
S>


Повторяешь ошибку Chez'a и Gurtovoy — с указателем функция не будет находится по ADL


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Невероятно, но факт! Не константные значения в компай
От: Lorenzo_LAMAS  
Дата: 08.02.07 08:12
Оценка:
R>Можно поподробнее и поаргументированнее.

А ты комо онлайн запусти в стрикт режиме и увидишь много интересного.
Of course, the code must be complete enough to compile and link.
Re[5]: Невероятно, но факт! Не константные значения в компай
От: Pavel Chikulaev Россия  
Дата: 08.02.07 08:13
Оценка:
Здравствуйте, remark, Вы писали:

R>Подсказка 1.


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


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

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

template<typename type>
struct magic
{
};


R>Подумай о POI. Когда в первый раз компилятор начинает компилировать специализацию шаблона. И когда он действительно видет, что какую-то функцию надо выносить в глобальное пространство, и видит какую именно. До POI, т.е. пока не требуется определения класса, компилятор не то что не обязан, он не может компилировать специализацию.

Это единственное исключение, но это так, т.е. компилятор должен пропускать все в шаблоне кроме друзей.
Re[5]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 08.02.07 08:15
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

R>>Можно поподробнее и поаргументированнее.


L_L>А ты комо онлайн запусти в стрикт режиме и увидишь много интересного.


"ComeauTest.c", line 9: warning: "int engine(magicc &, type &)" declares a
non-template function -- add <> to refer to a template instance
friend int engine(magicc&, type&);
^


Пожалуйста, мне не жалко


"ComeauTest.c", line 15: error: the size of an array must be greater than zero
char a[magic<>::val != magic<>::val ? 1 : -1];
^


Ошибка ни о чём не говорит. Где и что конкретно не так.


"ComeauTest.c", line 15: warning: variable "a" was declared but never referenced
char a[magic<>::val != magic<>::val ? 1 : -1];
^


Аааа... ты про это мне хотел сказать???


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

PC>Да именно так, т.е. равнозначно этому (кроме прав доступа)

PC>
PC>template<typename type>
PC>int engine(type);

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


Уж вот этому точно не равнозначно. Однозначно.
Тут шаблонная функция, а у меня не шаблонная. А это две большие разницы.

R>>Подумай о POI. Когда в первый раз компилятор начинает компилировать специализацию шаблона. И когда он действительно видет, что какую-то функцию надо выносить в глобальное пространство, и видит какую именно. До POI, т.е. пока не требуется определения класса, компилятор не то что не обязан, он не может компилировать специализацию.

PC>Это единственное исключение, но это так, т.е. компилятор должен пропускать все в шаблоне кроме друзей.

А можно ссылку на стандарт или ещё куда-то?
А если друг в шаблонном клсее, который вложен в другой шаблонный класс???... Ему придётся компилировать ещё и вложенный шаблонный класс??? ... Если вложенный шаблонный класс как-то хитро зависит от параметров шаблона объемлющего?...
Не очень понятно, как это должно/может работать...


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: Невероятно, но факт! Не константные значения в компа
От: Lorenzo_LAMAS  
Дата: 08.02.07 08:20
Оценка:
Здравствуйте, remark, Вы писали:

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


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

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

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

R>здесь

R>

Хехе, у них версия фронт-энда старее, чем у Комо онлайн.
Of course, the code must be complete enough to compile and link.
Re[3]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 08.02.07 08:20
Оценка:
Здравствуйте, remark, Вы писали:

NB>>вопрос по выделенному. при замене *(magicc*)0 на magicc() получаем одинаковые magic<>::val.

NB>>чем вызвано?

R>Чем компилил?


гсс 3.4

R>Это вообще не должно компилироваться, т.к. ты пытаешься сделать вызов конструктора до определения класса. Там, где ты написал magicc() видно только форвард объявление класса...


а не при создании первой переменной?
Re[3]: Невероятно, но факт! Не константные значения в компай
От: Tonal- Россия www.promsoft.ru
Дата: 08.02.07 08:20
Оценка:
Опаньки, протупил.
Re[4]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 08.02.07 08:21
Оценка:
Здравствуйте, Аноним, Вы писали:

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


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


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


R>>>>Пришло время очередного ресёрча


Ш>>>Хочу влить свою бочку дегтя в эту ложку сахарного сиропа.


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


R>>Какие моменты у тебя вызывают недоверие?



А>Для начала — разыменование нулевого указателя.


Пуристы могут заменить это разыменование на вызов функции:
magicc& get_some_magic();


R>>Почему?


А>Ты что, серьезно считаешь, что поиск имен зависит от того, что было инстанцировано, а что нет?


Я серьёзно считаю, что поиск имён зависит от того, что видно в POI.

Ш>>>3) Пользоваться такими изобретениями в реальной работе категорически нельзя. Ломиком по рукам.


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


А>Код с UB уже тоже.


Кроме нулевой ссылки ещё что-то есть?


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


R>>Это вообще не должно компилироваться, т.к. ты пытаешься сделать вызов конструктора до определения класса. Там, где ты написал magicc() видно только форвард объявление класса...


NB>а не при создании первой переменной?


Нет.
Вот смотри ещё 2 аналогичных примера, которые _не_ работают по той же причине:

template<typename type>
struct b {};


template<typename type>
struct d : b<d::inner> 
{
  typedef type inner;
};




template<typename type>
struct b 
{
  typedef typename type::inner inner;
};


template<typename type>
struct d : b<d> 
{
};



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

S>>А почему не зделать так?:


думаю, что в обявлении friend должно быть что-то, что инстанцирует magic<type,-1> (то есть не указатель)

но если friend действительно вводит нужную функцию в глобальное пространство и это корректно, тогда можно и указатель.

S>>
S>>template<typename type = int, int id = sizeof( engine( new magic<type,-1> ) ) >
S>>struct magic {
S>>    friend int engine( magic<type,-1> * );
S>>    static const int val = id;
S>>};
S>>


R>Повторяешь ошибку Chez'a и Gurtovoy — с указателем функция не будет находится по ADL


да вроде находится.
Re[5]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 08.02.07 08:50
Оценка:
Здравствуйте, remark, Вы писали:

R>>>Это вообще не должно компилироваться, т.к. ты пытаешься сделать вызов конструктора до определения класса. Там, где ты написал magicc() видно только форвард объявление класса...


NB>>а не при создании первой переменной?


R>Нет.


аналогичный пример
template< typename T, typename S> struct test;

template< typename T, typename S = typename test<T,void>::type >
struct test {
   typedef int type;
};

int main () {
   test<int> x;
}



R>Вот смотри ещё 2 аналогичных примера, которые _не_ работают по той же причине:


не аналогичных. ты тип используешь не в определении default параметра.
Re[9]: Будь твёрд в своей любви!
От: Erop Россия  
Дата: 08.02.07 09:13
Оценка:
Здравствуйте, remark, Вы писали:

R>Априори (без ссылок на стандарт) компилирование 3 самыми популярными и приближенными к стандарту компиляторами чего-то да стоит. По крайней мере того, что бы оппонент представил хотя бы какие-то факты, а не просто фразы, что это типа какая-то там некая давно известная дыра где-то


Ну дыра называется The Barton-Nackman Trick.
Но в этом случае всё происходит изнутри шаблона, всё-таки.
Как именно должны взаимодействовать глобальные функции, объявленные в разных инстанциациях шаблона я в стандарте не нашёл
Может плоъхо искал...

Но в целом, видимо есть, по крайней мере надежда, что стандарт можно и удобно трактовать так, чтобы было счастье. Но будет ли оно --
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Невероятно, но факт! Не константные значения в компайл-т
От: Pavel Chikulaev Россия  
Дата: 08.02.07 09:15
Оценка:
Здравствуйте, remark, Вы писали:

Посмотри всю ветку http://lists.boost.org/Archives/boost/2004/08/70668.php
Re[2]: Невероятно, но факт! Не константные значения в компай
От: Pavel Chikulaev Россия  
Дата: 08.02.07 09:22
Оценка:
Здравствуйте, Pavel Chikulaev, Вы писали:

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


PC>Посмотри всю ветку http://lists.boost.org/Archives/boost/2004/08/70668.php


И вот эту: http://lists.boost.org/Archives/boost/2004/12/77162.php
Re[9]: Невероятно, но факт! Не константные значения в компай
От: Erop Россия  
Дата: 08.02.07 09:27
Оценка:
Здравствуйте, remark, Вы писали:

R>Так же как и всё остальные.

R>Нет понятия каких-то "других" функций, есть просто функции и они все равнозначны и одинакого влияют на разрешение перегрузки.

Сутиь проблемы в следующем.
В С++ шаблоны определены очень запутано и непоследовательно. Например, относительно легко написать код, который будет зависеть не только от точки инстанциации шаблона, но ещё и от последовательности этих инстанциаций.
Когда инстанциации связаны между собой, то вроде как всё специфицировано, но вот когда они несвязаны никак, то, АФАИК это не специфицировано.
В принципе это правильно, так как предоставляет довольно полезную свободу авторам компиляторов. Скажем каждый шаблон, с каждым набором параметров хотя бы предсказуемо инстанцируется.
А так, от порядка инстанциации шаблонов в единице трансляции, начнёт зависеть то, что нужно генерить по шаблонам. Это приведёт к проблемам с ODR, например.

Так что, ИМХО и АФАИК это всё-таки особенность реализации шаблонов в используемых тобой компиляторах.
Например, может сломаться на компиляторе, который компилит все шаблоны в одну базу на проект, а потом оттуда их переиспользует, то может и не сработать
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: Невероятно, но факт! Не константные значения в компай
От: Erop Россия  
Дата: 08.02.07 09:31
Оценка:
Здравствуйте, remark, Вы писали:

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

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

Дырка состоит в том, что у инстанцирования шаблонного класса есть побочный эффект -- появляется объявление нешаблонной функции в объемлющем пространстве имён. На что именно влияет это объявление,а на что не влияет -- это вопрос очень тонкий.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Невероятно, но факт! Не константные значения в компай
От: Lorenzo_LAMAS  
Дата: 08.02.07 09:59
Оценка:
R>Я серьёзно считаю, что поиск имён зависит от того, что видно в POI.

Мне вот тоже влом думать Я написал простой пример:
template<class>
class A
{
   friend void fun(const A<char> *);
};

int main()
{
   A<char> * p = 0;
   fun(p);
}

Комо находит функцию.
Вижуал — лошит — не находит! Зато, если я добавляю
int main()
{
   A<int>a;
   A<char> *p = 0;
   fun(p);
}


Он уже может найти эту функцию. Так вот ты что, утверждаешь, что такое поведение вижуала правильное???
Кстати, а что за бредовую муру пишет вижуал, если сделать так:
int main()
{
   A<char> *p = 0;
   fun(p);
   A<int>a;

}

??
Of course, the code must be complete enough to compile and link.
Re[3]: Невероятно, но факт! Не константные значения в компай
От: Шахтер Интернет  
Дата: 08.02.07 13:42
Оценка:
Здравствуйте, remark, Вы писали:

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


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


R>>>Пришло время очередного ресёрча


Ш>>Хочу влить свою бочку дегтя в эту ложку сахарного сиропа.


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


R>Какие моменты у тебя вызывают недоверие?


Я задал конкретный вопрос здесь
Автор: Шахтер
Дата: 07.02.07
.

Пока я не получил ответа.


Ш>>2) Если это не баг, то это дыра в стандарте. Срочно фиксить стандарт.


R>Почему?


Потому что нарушаются локальность поведения и принцип однозначности значения шаблона как функции аргументов. Нарушение этих базовых принципов ничем не оправдано.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[7]: Невероятно, но факт! Не константные значения в компай
От: Roman Odaisky Украина  
Дата: 08.02.07 16:29
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Лично для меня очевидно, что поиск имен должен работать всегда одинаково и не зависеть от того, что и сколько раз инстанцировалось.


По-моему, тут не всё так просто.

template <class X>
class C
{
    friend void doSomething(X &);
}
(http://rsdn.ru/Forum/Message.aspx?mid=2340657&amp;only=1
Автор: remark
Дата: 08.02.07
)

Зависит ли здесь поиск имен от того, чем инстанцируется C? По-моему, очень даже зависит.
До последнего не верил в пирамиду Лебедева.
Re[2]: Невероятно, но факт! Не константные значения в компай
От: Кодт Россия  
Дата: 08.02.07 17:22
Оценка:
Здравствуйте, Шахтер, Вы писали:

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

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

Больше всего это похоже на нарушение ODR.
Вот простенький пример, делающий то же самое абсолютно без наворотов.
char foo(...);

int const x = sizeof(foo(char(0)));

int foo(int);

int const y = sizeof(foo(char(0)));

double foo(char);

int const z = sizeof(foo(char(0)));

Разница лишь в том, что мы не автоматически, а вручную ввели новые определения. Ну и количество уточнений ограничено тремя: char < int < ...

И если это действительно ODR, то программа ill-formed, а поведение компилятора не определено. Тот факт, что большинство компиляторов пошли одним путём — поздравляю.
Могли и не пойти, кстати.
// генератор последовательности (любой)
template<bla-bla-bla> struct sequence { bla-bla-bla };

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

t1 x1;
t1 x2;
t1 x3;
t2 x4;
t2 x5;
t2 x6;

Если компилятор в точке объявления t1 запоминает все дефолтные параметры, доступные на тот момент, то
— t1 != t2
— typeof(x1) == typeof(x2) == typeof(x3)
А если компилятор полагает, что sequence<> и в африке sequence<>, запоминает, что "вот здесь параметры — дефолтные" и затем разворачивает их по месту использования, то
— t1 эквивалентно t2 (т.е. x4...x6 продолжают серию x1...x3)
— typeof(x1) != typeof(x2) != typeof(x3)
Кстати, от VC<=7.0 можно было ожидать именно такого... Раз уж он шаблоны запоминал как AST без проверок.

А особенно прикольно это будет смотреться, когда шаблон дважды встретится в одном выражении. Который будет какой?
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[3]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 08.02.07 17:45
Оценка:
Здравствуйте, Кодт, Вы писали:

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


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

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

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

К>Вот простенький пример, делающий то же самое абсолютно без наворотов.
К>char foo(...);

К>int const x = sizeof(foo(char(0)));

К>int foo(int);

К>int const y = sizeof(foo(char(0)));

К>double foo(char);

К>int const z = sizeof(foo(char(0)));

К>Разница лишь в том, что мы не автоматически, а вручную ввели новые определения. Ну и количество уточнений ограничено тремя: char < int < ...

а где здесь нарушение ODR?
объявлено 3 разных функции.

К>И если это действительно ODR, то программа ill-formed, а поведение компилятора не определено. Тот факт, что большинство компиляторов пошли одним путём — поздравляю.

К>Могли и не пойти, кстати.

ну, порядок инстанцирования вроде более менее определен. собственно, это и ипользуется.

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

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

К>t1 x1;
К>t1 x2;
К>t1 x3;
К>t2 x4;
К>t2 x5;
К>t2 x6;

К>Если компилятор в точке объявления t1 запоминает все дефолтные параметры, доступные на тот момент, то

да, прикольно.
но все таки typedef это не макрос, поэтому компилятор должен выводить дефолтное значение по месту определения тайпдефа.

template< typename T, typename S = typename T::type > struct test;
typedef test<int> error;
Re[6]: Невероятно, но факт! Не константные значения в компай
От: night beast СССР  
Дата: 09.02.07 03:50
Оценка:
Здравствуйте, Pavel Chikulaev, Вы писали:

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


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

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

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


свой резон в этом есть. но что компилятор должен делать в таком случае:
template<typename T>
struct magic
{
    typedef typename remove_ref<T>::type type;

    friend int engine(type);
};
Re[10]: Будь твёрд в своей любви!
От: remark Россия http://www.1024cores.net/
Дата: 09.02.07 05:09
Оценка:
Здравствуйте, Erop, Вы писали:

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


R>>Априори (без ссылок на стандарт) компилирование 3 самыми популярными и приближенными к стандарту компиляторами чего-то да стоит. По крайней мере того, что бы оппонент представил хотя бы какие-то факты, а не просто фразы, что это типа какая-то там некая давно известная дыра где-то


E>Ну дыра называется The Barton-Nackman Trick.

E>Но в этом случае всё происходит изнутри шаблона, всё-таки.
E>Как именно должны взаимодействовать глобальные функции, объявленные в разных инстанциациях шаблона я в стандарте не нашёл
E>Может плоъхо искал...


Моё мнение такое, что тут никаких особых правил и не надо — всё работает по общим правилам.


E>Но в целом, видимо есть, по крайней мере надежда, что стандарт можно и удобно трактовать так, чтобы было счастье. Но будет ли оно --


У меня будет, а Вы смотрите сами...


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

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


R>>Так же как и всё остальные.

R>>Нет понятия каких-то "других" функций, есть просто функции и они все равнозначны и одинакого влияют на разрешение перегрузки.

E>Сутиь проблемы в следующем.

E>В С++ шаблоны определены очень запутано и непоследовательно. Например, относительно легко написать код, который будет зависеть не только от точки инстанциации шаблона, но ещё и от последовательности этих инстанциаций.
E>Когда инстанциации связаны между собой, то вроде как всё специфицировано, но вот когда они несвязаны никак, то, АФАИК это не специфицировано.
E>В принципе это правильно, так как предоставляет довольно полезную свободу авторам компиляторов. Скажем каждый шаблон, с каждым набором параметров хотя бы предсказуемо инстанцируется.
E>А так, от порядка инстанциации шаблонов в единице трансляции, начнёт зависеть то, что нужно генерить по шаблонам. Это приведёт к проблемам с ODR, например.

Вот к проблемам с ODR тут ничего не приведёт.
По факту у меня получается не более, чем:
magic<0>::val;
magic<1>::val;
magic<2>::val;


Такой код можно и руками написать.
Тут ODR _не_ нарушается, и следовательно привести к нарушению ODR в будущем не может. Смотри, например, мою реализацию определения смещения членов в классе — все классы, которые зависят от magic — просто тоже становятся разными классами (точнее разными специализациями).

E>Так что, ИМХО и АФАИК это всё-таки особенность реализации шаблонов в используемых тобой компиляторах.

E>Например, может сломаться на компиляторе, который компилит все шаблоны в одну базу на проект, а потом оттуда их переиспользует, то может и не сработать

Каким образом там это сломается? У меня ODR нигде не нарушается. Хоть в одну базу их клади, хоть нет, неважно.


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

L_L>Кстати, на случай, если ты не понял, к чему был мой пример — вот еще один:


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

L_L>Вот так вот работает и VC

L_L>Но это ИМХО говорит лишь о некоторой его кривизне, которую и хочет использовать автор исходного сообщения.


В конце концов на комо никто не работает — все работают на gcc/msvc — а у них такая модель компиляции шаблонов
Кстати в бусте тоже присутствуют всякие нехорошие моменты и затычки — но они ориентируются именно на работоспособность кода хотя бы под двумя компиляторами — причём зачастую работа под двумя компиляторами достигается по разному


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: Aaaaaaaaaaaaaaaaa
От: remark Россия http://www.1024cores.net/
Дата: 10.02.07 08:50
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Кстати, на случай, если ты не понял, к чему был мой пример — вот еще один:


А вот ещё один занятный пример:

char fff(...);

template<typename type> struct X;

void f1()
{
  char a[sizeof(fff((X<int>*)0)) == 1 ? 1 : -1]; (void)a;
}

template<typename type> struct X
{
  friend int fff(X*) {return 0;};
};

int main()
{
  f1();
  char a[sizeof(fff((X<int>*)0)) == 4 ? 1 : -1]; (void)a;
}


Comeau online компилит
К чему я это, я сходу не скажу


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

R>Каким образом там это сломается? У меня ODR нигде не нарушается. Хоть в одну базу их клади, хоть нет, неважно.


У тебя-то ODR не нарушается, но вот, если бы компиляторы работали так, как ты хочешь, то легко бы могла нарушаться.
В этом проблема.
поэтому работать может как-то неожиданно. Ты же довольно тонкой особенностью реализации пользуешься?
НУ а попробовать на трансляторе с общей базой шаблонов я тебе посоветовал потому, что там шаблоны оборабатываются сильно не так, как в GCC, например.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Невероятно, но факт! Не константные значения в компай
От: Erop Россия  
Дата: 10.02.07 10:18
Оценка:
Здравствуйте, remark, Вы писали:

R>Я надеюсь его работоспособность не вызывает вопросов. Иначе это уже не ко мне.

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

Но ты-то немного другой пример написал...
Ты же находишь другой engine, чем подставляемый...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Невероятно, но факт! Не константные значения в компай
От: Шахтер Интернет  
Дата: 10.02.07 10:28
Оценка:
Здравствуйте, Кодт, Вы писали:

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


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


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

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

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


К>Хотя ситуация, когда одно и то же выражение в разных частях одного и того же scope резолвится по-разному — настораживает...


Это плохая практика программирования.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Для тупых, посните, всё-таки?
От: Константин Л.  
Дата: 10.02.07 10:53
Оценка:
Здравствуйте, 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>А то я что-то никак не въеду


и почему id должен быть всегда разным? не очевидно.
Re[6]: Невероятно, но факт! Не константные значения в компай
От: Erop Россия  
Дата: 10.02.07 10:56
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Да нет, не будет это работать.


Совершенно согласен. только формулировочку можно смягчить на "не обязана работать на соответсвующем стандарту комиляторе".

Идея всего хака в том, что в принципе компилятьору никто не запрещает инстанцировать какие-нибудь левые лаблорны, если ему от чего-то это удобно. И пытаются ловить побочные эффекты таких вот инстациаций, но это все от компилера всё-таки зависит
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Для тупых, посните, всё-таки?
От: Erop Россия  
Дата: 10.02.07 11:21
Оценка:
Здравствуйте, Константин Л., Вы писали:

E>>А то я что-то никак не въеду

КЛ>и почему id должен быть всегда разным? не очевидно.

ИМХО он никогда не должен. И возникает вопрос о том, может ли?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Aaaaaaaaaaaaaaaaa
От: Lorenzo_LAMAS  
Дата: 12.02.07 08:28
Оценка:
Здравствуйте, remark, Вы писали:

R>А вот ещё один занятный пример:


R>char fff(...);

R>template<typename type> struct X;

R>void f1()
R>{
R>  char a[sizeof(fff((X<int>*)0)) == 1 ? 1 : -1]; (void)a;
R>}

R>template<typename type> struct X
R>{
R>  friend int fff(X*) {return 0;};
R>};

R>int main()
R>{
R>  f1();
R>  char a[sizeof(fff((X<int>*)0)) == 4 ? 1 : -1]; (void)a;
R>}
R>


R>Comeau online компилит

R>К чему я это, я сходу не скажу

Ээээ, я думаю, дело обстоит так. Т.к. f1 у тебя не шаблон, то тут все проще, никаких двухфазных поисков, никаких ПОИ. "Обычный" поиск имен находит функцию с ... . АДЛ ничего не находит (он и не может видеть то, что будет объявлено ниже).

Т.е. аналогично:
#include <iostream>

void fun(...)
{
   std::cout<<"fun(...)\n";
}

struct A;

void g()
{
   A * p = 0;
   fun(p);
}

void fun(A *)
{
   std::cout<<"fun(A *)\n";
}

int main()
{
   g();
}


Вызвана будет fun(...). Ну а в main в твоем исходном примере
у тебя уже есть нужное объявление функции друга, обычный поиск имен его не найдет, его найдет ADL.
Of course, the code must be complete enough to compile and link.
Re[9]: Невероятно, но факт! Не константные значения в компай
От: Lorenzo_LAMAS  
Дата: 12.02.07 08:31
Оценка:
Здравствуйте, remark, Вы писали:

R>В конце концов на комо никто не работает — все работают на gcc/msvc — а у них такая модель компиляции шаблонов

R>Кстати в бусте тоже присутствуют всякие нехорошие моменты и затычки — но они ориентируются именно на работоспособность кода хотя бы под двумя компиляторами — причём зачастую работа под двумя компиляторами достигается по разному

R>




Самое обидное, это когда комо начинает действительно необъяснимо глюкать Такие примеры бывают — вон, недавно что-то спрашивали про sizeof ("такой простой sizeof" или что-то в этом роде, там можно было заметить странное поведение комо)
Of course, the code must be complete enough to compile and link.
Re[12]: Невероятно, но факт! Не константные значения в компа
От: Sm0ke Россия ksi
Дата: 12.02.07 09:53
Оценка:
Здравствуйте, Erop, Вы писали:

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


R>>Каким образом там это сломается? У меня ODR нигде не нарушается. Хоть в одну базу их клади, хоть нет, неважно.


E>У тебя-то ODR не нарушается, но вот, если бы компиляторы работали так, как ты хочешь, то легко бы могла нарушаться.

E>В этом проблема.
E>поэтому работать может как-то неожиданно. Ты же довольно тонкой особенностью реализации пользуешься?
E>НУ а попробовать на трансляторе с общей базой шаблонов я тебе посоветовал потому, что там шаблоны оборабатываются сильно не так, как в GCC, например.

Такой трюк может привести к ODR

рассмотрим пример с 3-мя заголовочными файлами
file_01.h:
#pragma once

#include "magic.h"

struct some1 : pubilc magic<>
{};


file_02.h:
#pragma once

#include "magic.h"

struct some2 : pubilc magic<>
{};


test.h:
#pragma once

#include "magic.h"
// включаем только второй файл (1)
#include "file_02.h"

struct test : pubilc magic<>
{
  typedef
    some2
    type;
  type value;
};


test.cpp
#include "test.h"

// какой-то код


main.cpp
// включаем и первый файл, потом второй, потом test.h
#include "file_01.h"
#include "file_02.h"
#include "test.h"

int main()
{
  test t;
  return 0;
}


Как видно от порядка включения файлов file_01.h и file_02.h меняется определение класса test
Re[13]: Невероятно, но факт! Не константные значения в компа
От: Erop Россия  
Дата: 12.02.07 16:08
Оценка:
Здравствуйте, Sm0ke, Вы писали:

S>Как видно от порядка включения файлов file_01.h и file_02.h меняется определение класса test


1) Конечно может вызвать .
2) Мало ли порядок включения каких хедеров влияет на компиляцию?

Тут будет влиять ещё и порядок инстанцирования шаблонов в единице трансляции.

Скажем так пишем:

void my_processor( ... );
template<class T>
class MyArray : public std::vector<T> {
    friend void my_processor( T );
public:
    void Process()
    {
        for( int i = 0; i < size(); i++ )
             my_processor( i );
    }
};



И теперь код, вызывающий метод MyArray::Process будет зависеть от того, какие именно MyArray<T> уже были инстанциированы к моменту инстанциации вызова этого метода в данной единице трансляции
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[14]: Невероятно, но факт! Не константные значения в компа
От: night beast СССР  
Дата: 13.02.07 05:31
Оценка:
Здравствуйте, Erop, Вы писали:

E>Скажем так пишем:


E>void my_processor( ... );
E>template<class T>
E>class MyArray : public std::vector<T> {
E>    friend void my_processor( T );
E>public:
E>    void Process()
E>    {
E>        for( int i = 0; i < size(); i++ )
E>             my_processor( i );
E>    }
E>};



E>И теперь код, вызывающий метод MyArray::Process будет зависеть от того, какие именно MyArray<T> уже были инстанциированы к моменту инстанциации вызова этого метода в данной единице трансляции


было бы интересно глянуть, как ты вызываешь MyArray::Process не инстанцировав MyArray
Re[15]: Невероятно, но факт! Не константные значения в компа
От: Erop Россия  
Дата: 13.02.07 12:22
Оценка:
Здравствуйте, night beast, Вы писали:

NB>было бы интересно глянуть, как ты вызываешь MyArray::Process не инстанцировав MyArray


сравни

void f1() { MyArray<char>().Process();
void f2() { MyArray<int>().Process();


void f2() { MyArray<int>().Process();
void f1() { MyArray<char>().Process();
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[16]: Невероятно, но факт! Не константные значения в компа
От: night beast СССР  
Дата: 13.02.07 14:41
Оценка:
Здравствуйте, Erop, Вы писали:

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


NB>>было бы интересно глянуть, как ты вызываешь MyArray::Process не инстанцировав MyArray


E> сравни


а, вот ты о чем
так вроде уж выяснили, что не работает здесь
Автор: Шахтер
Дата: 10.02.07
Re[17]: Невероятно, но факт! Не константные значения в компа
От: Erop Россия  
Дата: 13.02.07 14:48
Оценка:
Здравствуйте, night beast, Вы писали:

NB>так вроде уж выяснили, что не работает здесь
Автор: Шахтер
Дата: 10.02.07

Так а я о чём?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: И всё же
От: Roman Odaisky Украина  
Дата: 17.02.07 15:01
Оценка:
Что мешает ADL найти эту функцию?

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);
До последнего не верил в пирамиду Лебедева.
Re[2]: Для тупых, посните, всё-таки?
От: IROV..  
Дата: 17.02.07 15:09
Оценка:
Здравствуйте, 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

1
4
4
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 я написал вот так.

вот тут!
Автор: IROV..
Дата: 07.02.07
я не волшебник, я только учусь!
Re[2]: Ремарки от ремарка :)
От: Roman Odaisky Украина  
Дата: 17.02.07 15:47
Оценка:
И еще. Какая муха кусает gcc 4.1.2 инстанцировать Z<0>?

template <class T>
T& make();

template <int N>
struct Size
{
    typedef char (&type)[N];
};

///////////////////////////////////////////////////////////

Size<1>::type g(...);

template <int N>
class Z
{
    friend typename Size<N>::type g(Z<0> const &);
};

int main()
{
    std::cout << sizeof(g(make<Z<0> >())) << std::endl;
    new Z<2>;
    std::cout << sizeof(g(make<Z<0> >())) << std::endl;
}
До последнего не верил в пирамиду Лебедева.
Re[3]: Прикольно. А теперь может кто-то на мой вопрос ответи
От: Erop Россия  
Дата: 18.02.07 11:03
Оценка:
Здравствуйте, IROV.., Вы писали:

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 для всех участвующих в процессе шаблонов.

IRO>все просто.

Спасибо за разъяснения
К сожалению, ты ответил не на мой вопрос.
Свой вопрпос я выделил полужирным, для удобства.
А замысел ремарка я понял сразу. Только мне кажется, что это всё глюки компилятора

IRO>но как только мы инстанциировали класс magic, то появляется magic — friend int engine(magicc&, type&);

Прекрасно! Где будет POI? Перед функцией main? Или после?
Если перед, то почему не будет действовать на первое же упоминание, если после, то почему будет действовть на второе?..

3E>>А то я что-то никак не въеду


IRO>вот тут!
Автор: IROV..
Дата: 07.02.07

Там вопрос, между прочим, тот же...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: всё ещё прикольнее, чем кажется на первый взгляд!
От: Erop Россия  
Дата: 18.02.07 11:07
Оценка:
Здравствуйте, remark, Вы писали:

R>Тем не менее похоже, что не работает это исключительно на Comeau. И это остаётся рабочим вариантом на msvc71/msvc80/gcc34/gcc41/icc70/icc80/edg. Впечатляет, правда? Не работает только на самых свежих фронт-ендах edg.

R>Имхо список компиляторов достаточен даже для включения в boost

На самом деле прикольно, что глюк совпадает. Я бы озаботился вопросом о переиспользовании чужого кода...
Чтобы было понятнее о чём таки я, надо попробовать объяснить как же всё-таки работает компилятор?
Чтобы было легче, надо ответить на уточнённый вспомогательный вопрос
Автор: Erop
Дата: 18.02.07
, ну или на его первоначальную форму
Автор: Erop
Дата: 10.02.07
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: всё ещё прикольнее, чем кажется на первый взгляд!
От: Ka3a4oK  
Дата: 26.02.07 21:49
Оценка:
Уж не намекаете ли ва на то, что злые коммерческие дядьки из Microsoft и Intel использовали(читай спиз$или) беззащитный, открытый GPL-ый(?) код синтаксического анализа gcc? И теперь цинично делают деньги? Как такое можно подумать.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[4]: всё ещё прикольнее, чем кажется на первый взгляд!
От: Erop Россия  
Дата: 27.02.07 08:53
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

KK>Уж не намекаете ли ва на то, что злые коммерческие дядьки из Microsoft и Intel использовали(читай спиз$или) беззащитный, открытый GPL-ый(?) код синтаксического анализа gcc? И теперь цинично делают деньги? Как такое можно подумать.


Я намекаю на то, что не совсем понятно как хитро так работают инстанциаторы шаблонов в разных компиляторах.
Наверняка авторы разных компиляторов не только решали схожие задачи и читали схожиекниги, но и смтрели на изделия конкурентов. И то, что глюк столь распрорстранён наверняка имеет какую-то пичину. Если это не банальный цельнотянутый код (я в это не верю, так как даже если код тянут, то его ремасерят, особенно, если он живёт много версий и поддерживается и развивается), то навкрняка есть какая-то довольно глубокая и нетривиальная причина...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Невероятно, но факт! Не константные значения в компайл-т
От: tilarids Украина tilarids.blogspot.com
Дата: 20.06.07 12:45
Оценка:
Здравствуйте, remark, Вы писали:

R>Пришло время очередного ресёрча


Тема достаточно, большая, найти что-либо сложно, а понять — тем более. Хочу использовать для Перенести из run-time в compile-time
Автор: tilarids
Дата: 15.06.07


Все реализовано:

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, второй 1
    static const int i = compile_time_flag::flag<char>::IsTrue;//0
    static const int j = compile_time_flag::flag<double>::IsTrue;//0
    static const int k = compile_time_flag::flag<double>::IsTrue;//1
    static const int l = compile_time_flag::flag<char>::IsTrue;//1
    static const int m = compile_time_flag::flag<char>::IsTrue;//1
    std::cout<<i<<j<<k<<l<<m;//00111
}



Все работает на 8.0 студии именно так, как мне хочется. Естественно, захотелось, чтобы и под другими компиляторами работало. remark обещает работоспособность под кучей компиляторов, кроме Comeau. Пытался найти объяснение. Находил нечто похожее, например здесь
Автор: Pavel Chikulaev
Дата: 08.02.07
. Но самое интересное, что Comeau не работает так, как описано в этом посте! То есть, в строке

char a[compile_time_flag::flag<int>::IsTrue != compile_time_flag::flag<int>::IsTrue ? 1 : -1];


для Comeau Online оба значения равны 0! Что означает, что при вычислении default параметра id всегда используется функция с эллипсисом. Несмотря на то, что ADL должен найти friend функцию(хотя бы в одном месте).

Итак, объясните мне, почему Comeau работает так(желательно с указанием стандарта), или относим Comeau к не поддерживающим стандарт компиляторам и еще раз апплодируем идее
Ну, и как оно должно все-таки работать, желательно — список действий компилятора.
Всем заранее спасибо
<вырезано, дабы сохранить место на сервере>
Re[2]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 20.06.07 17:49
Оценка:
Здравствуйте, tilarids, Вы писали:

T>для Comeau Online оба значения равны 0! Что означает, что при вычислении default параметра id всегда используется функция с эллипсисом. Несмотря на то, что ADL должен найти friend функцию(хотя бы в одном месте).


T>Итак, объясните мне, почему Comeau работает так(желательно с указанием стандарта), или относим Comeau к не поддерживающим стандарт компиляторам и еще раз апплодируем идее

T>Ну, и как оно должно все-таки работать, желательно — список действий компилятора.


Comeau судя по всему как раз единственный делает правильно. А все остальные компиляторы очень подозрительно делают одну и ту же ошибку. Хотя вопрос очень тёмный и с уверенностью здесь сказать что-либо сложно.

Как это должно работать (как делает Comeau).
Если функция может быть найдена с помощью обычного поиска или ADL, то она должна быть найдена в любом случае. Результат поиска не должен завистеть ни от чего, в том числе от того какие шаблоны были инстанциированы до этой точки.

Как делают все остальные.
Функция находится с помощью ADL только после того, как шаблон её содержащий был инстанциирован.

Т.е. компилятор должен в данном случае при осуществлении ADL инстанциировать все классы, которые относятся к типу каждого параметра функции и посмотреть, не появилось ли новой подходящей функции во время этого инстанциирования. Как-то так.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Невероятно, но факт! Не константные значения в компай
От: Lepsik Гондурас https://www.kirdyk.club/
Дата: 20.06.07 18:05
Оценка:
R>Во-первых, это уже круто!
R>Во-вторых, что такое VC9

VS2008
Re[3]: Невероятно, но факт! Не константные значения в компай
От: tilarids Украина tilarids.blogspot.com
Дата: 20.06.07 20:45
Оценка:
Здравствуйте, 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[4]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 20.06.07 20:58
Оценка:
Здравствуйте, tilarids, Вы писали:

T>Comeau Online демонстрирует вообще замечательное поведение — там просто ADL не работает.


LROTF

Ты тут просто неправильно написал. Ты не ту функцию другом объявляешь или точнее другом не того класса.
Хинт: тип flag<no> и тип flag<yes> — совершенно разные типы. При ADL поиске через один тип не будут находится функции связанные с другим типом.
Если не изменяет память, в этом топике я приводил решение для этой проблемы.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Невероятно, но факт! Не константные значения в компай
От: Yoh Asakura  
Дата: 20.06.07 21:08
Оценка:
Не согласен, ибо тон задают создатели стандарта и производители компилятора, а все остальные вынуждены писать в своем коде обходные макросы =)
Re[4]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 20.06.07 21:29
Оценка:
Здравствуйте, Yoh Asakura, Вы писали:

YA>Не согласен, ибо тон задают создатели стандарта и производители компилятора, а все остальные вынуждены писать в своем коде обходные макросы =)


Какие есть примеры, когда производитель массового продукта не обратно совместимо менял поведение и рушил тем самым клиентский код?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: Невероятно, но факт! Не константные значения в компай
От: Yoh Asakura  
Дата: 20.06.07 21:35
Оценка:
Производители массового продукта подобные вещи наружу не выносят, а отдают откомпелированный код.
А за примерами идти надо в OpenSource — так он наполнен подобным, когда изменение в GCC по исправлению баги приводит к тому, что даже известные OpenSource библиотеки не собираются, не говоря уже попытке собрать старую версию ядра новым компилятором...
Re[2]: Объясняю ещё раз
От: Erop Россия  
Дата: 21.06.07 06:54
Оценка:
Здравствуйте, tilarids, Вы писали:

T>Итак, объясните мне, почему Comeau работает так(желательно с указанием стандарта), или относим Comeau к не поддерживающим стандарт компиляторам и еще раз апплодируем идее

T>Ну, и как оно должно все-таки работать, желательно — список действий компилятора.
T>Всем заранее спасибо

ИМХО этот код работать не должен. Это если по стандарту.

Чтобы убедить меня в обратном, укажи пожалуйста в каких именно местах единицы трансляции должны находиться POI каких именно шаблонов,
чтобы в этой строчке
char a[compile_time_flag::flag<int>::IsTrue != compile_time_flag::flag<int>::IsTrue ? 1 : -1];
"compile_time_flag::flag<int>::IsTrue" компилировалось по разному слева и справа от оператора !=.

То что на остальных компиляторах этот хак работает не о чём, кроме неаккуратного использования в этих компиляторах статических переменных не говорит
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Невероятно, но факт! Не константные значения в компай
От: Erop Россия  
Дата: 21.06.07 06:56
Оценка:
Здравствуйте, remark, Вы писали:

R>Сия магия заканчивается обычно тем, что производителям компиляторов приходится пожизненно поддерживать флаги для обратной совместимости поведения. Даже если это было не стандартное поведение или просто баг.


R>


Не, ну это ты себе льстишь всё-таки. Хотя хак классный, жалко, что не по стандарту
Для того, чтобы производители компилятора поддерживали в следующих версиях багу, как фичу, требуется, чтобы багу начали использовать таки массово
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Невероятно, но факт! Не константные значения в компай
От: Erop Россия  
Дата: 21.06.07 06:57
Оценка:
Здравствуйте, remark, Вы писали:

R>Какие есть примеры, когда производитель массового продукта не обратно совместимо менял поведение и рушил тем самым клиентский код?



Фирму Microsoft знаешь?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Невероятно, но факт! Не константные значения в компай
От: tilarids Украина tilarids.blogspot.com
Дата: 21.06.07 13:29
Оценка:
Здравствуйте, remark, Вы писали:

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


T>>Comeau Online демонстрирует вообще замечательное поведение — там просто ADL не работает.


R>LROTF


R>Ты тут просто неправильно написал. Ты не ту функцию другом объявляешь или точнее другом не того класса.

R>Хинт: тип flag<no> и тип flag<yes> — совершенно разные типы. При ADL поиске через один тип не будут находится функции связанные с другим типом.
R>Если не изменяет память, в этом топике я приводил решение для этой проблемы.

R>


Так. Сейчас будем очень аккуратно разбираться. Дело в том, что это твой же пример — я просто его чуть-чуть переделал. И поверил тебе, что там ADL. Могу даже на твоем же коде продемонстрировать.

char engine(...);//Всего одна функция

template<typename, int> struct magic;
typedef magic<char, -1> magicc;//При typedef ничего не инстанцируется - все еще одна функция

template<typename type = int, int id = sizeof(engine(*(magicc*)0, *(type*)0))>
//magicc снова не инстанцируется - это не нужно
//то есть, в magicc:: нет friend int engine(magicc&, type&);
//получается id = sizeof возвращаемого значения первой функции(с эллипсисом)
struct magic
{
    friend int engine(magicc&, type&);//появляется magic<int,sizeof(char)>::engine(magicc&, type&)
        //При следуюущем вызове ADL действительно работать не будет, ведь ADL по magicc - ничего не найдет, ибо magicc не инстанцируется никогда.
    static const int val = id;
};

int main()
{
    char a[magic<>::val != magic<>::val ? 1 : -1];//Почему же тогда это работает в стольких компиляторах????
}


По поводу моего примера — я бы не присылал его, если бы не проверил — он работает также, как и твой. Во всех компайлерах, мне доступных.

Comeau действительно отрабатывает правильно. Потому что нет ADL. Я решил туда его добавить — для этого нужно просто инстанцировать класс, который передается параметром в функцию ПОСЛЕ первого вызова этой функции. Сделал вот такую вещь:

        struct yes{};
    struct no{char _no[2];};

    no check(...);
    template <class,class,int> struct flag;

    template <class T> T& make_ref();
    template <class T> T* make_ptr();
    template <typename T> yes is_same_tester(T*, T*);
    no is_same_tester(...); 

    template< class T1, class T2 >
    struct is_same//Проверка типов на равенство
    {

        enum { value = sizeof(is_same_tester(make_ptr<T1>(),make_ptr<T2>()))==sizeof(yes)};
    };

    template <int val,class true_class,class false_class>
    struct typeselector;//Выбирает тип в зависимости от значения val

    template <class true_class,class false_class>
    struct typeselector<0,true_class,false_class>
    {
        typedef false_class type;//если 0 - то здесь - false_class
    };

    template <class true_class,class false_class>
    struct typeselector<1,true_class,false_class>
    {
    
        typedef true_class type; //если 1 - то здесь - true_class
    };

    class Dummy//пустой класс, нужен для наследования
    {
    };



    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 : public typeselector<is_same<flag<flag_type,type,id>,flag<flag_type,no,-1> >::value,Dummy,flag<flag_type,no,-1> >::type
    //Вся идея заключается в применении наследования для форсирования инстанцирования нужного нам класса. Так как оно должно обрабатываться после подсчёта default параметров, то мы все так же получаем 0 при первом инстанцировании.
    //Так как наследоваться от самого себя нельзя, то делаем проверку типов, и в случае инстанцирования flag<flag_type,no,-1> наследуемся от Dummy
    {
        friend yes check(flag<flag_type,no,-1>&,type&);
        static const int IsTrue = id;
    };


char a[flag<int>::IsTrue == 0 ? 1 : -1];//0
char b[flag<int>::IsTrue == 1 ? 1 : -1];//1 - вот здесь комо валится
//Все прекрасно работает на студии, но все так же не работает на Comeau


Извиняюсь за корявость примера, возможно там где-то ошибки внутри кода. Если кто сможет написать, чтобы работало ADL без всяких лишних телодвижений(элементарная подстановка в расчёте id другого имени класса почему-то приводит к тому, что все перестает работать) — просим. Кто сможет объяснить — в чем я не прав, или, в другом случае, привести более короткий и красивый пример — буду рад.

PS. Кстати, комо инстанцирует шаблоны в моем случае именно в таком порядке:
1. flag<int,yes,0>
2. flag<int,no,-1>//Первые два определил по сообщениям об ошибках
3. Не инстанцируется flag<int,yes,1>
<вырезано, дабы сохранить место на сервере>
Re[6]: Невероятно, но факт! Не константные значения в компай
От: remark Россия http://www.1024cores.net/
Дата: 21.06.07 13:46
Оценка:
Здравствуйте, tilarids, Вы писали:

T> char a[magic<>::val != magic<>::val ? 1 : -1];//Почему же тогда это работает в стольких компиляторах????


Потому что на них на всех ещё одна бага, они считают, что flag<yes> и flag<no> один тип в плане ADL и друзей.

T>char b[flag<int>::IsTrue == 1 ? 1 : -1];//1 — вот здесь комо валится


Всё правильно валится, он то как раз по стандарту всё делает.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Объясняю ещё раз
От: tilarids Украина tilarids.blogspot.com
Дата: 21.06.07 13:47
Оценка:
Здравствуйте, Erop, Вы писали:

E>ИМХО этот код работать не должен. Это если по стандарту.


E>Чтобы убедить меня в обратном, укажи пожалуйста в каких именно местах единицы трансляции должны находиться POI каких именно шаблонов,

E>чтобы в этой строчке
char a[compile_time_flag::flag<int>::IsTrue != compile_time_flag::flag<int>::IsTrue ? 1 : -1];
E>
"compile_time_flag::flag<int>::IsTrue" компилировалось по разному слева и справа от оператора !=.


E>То что на остальных компиляторах этот хак работает не о чём, кроме неаккуратного использования в этих компиляторах статических переменных не говорит


Я тоже согласен, что код работать никак не должен. Ибо результат не должен зависеть от порядка инстанцирования шаблонов. Я хочу сделать нечто другое: некое подобие init. То бишь, меня не волнует, в каком порядке инстанцировались шаблоны. Мне хочется, чтобы если где-нибудь, или когда-нибудь участвовал некий специально сформированный шаблон, то автоматически где-нибудь некая сущность это в себе хранила. Что-то вроде:

//идеальный вариант
work_if<verifier<type>::inited,Dummy,Worker>().Work();//Использует класс в зависимости от значения
init<type>::init;//Если оно здесь есть, то verifier<type>::inited везде становится равным 1, иначе - 0
work_if<verifier<type>::inited,Dummy,Worker>().Work();//Использует класс в зависимости от значения
work_if<verifier<type>::inited,Dummy,Worker>().Work();//Использует класс в зависимости от значения

//удовлетворюсь таким - раз уж столько компиляторов подряд инстанцируют
//его уже можно реализовать - могу кинуть код - жаль, не свой.
init<type>::init;//Если оно здесь есть, то verifier<type>::inited везде становится равным 1, иначе - 0
work_if<verifier<type>::inited,Dummy,Worker>().Work();//Использует класс в зависимости от значения
work_if<verifier<type>::inited,Dummy,Worker>().Work();//Использует класс в зависимости от значения
work_if<verifier<type>::inited,Dummy,Worker>().Work();//Использует класс в зависимости от значения


PS. Пока писал — появились идеи
<вырезано, дабы сохранить место на сервере>
Re[7]: Невероятно, но факт! Не константные значения в компай
От: tilarids Украина tilarids.blogspot.com
Дата: 21.06.07 13:50
Оценка:
Здравствуйте, remark, Вы писали:

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


T>> char a[magic<>::val != magic<>::val ? 1 : -1];//Почему же тогда это работает в стольких компиляторах????


R>Потому что на них на всех ещё одна бага, они считают, что flag<yes> и flag<no> один тип в плане ADL и друзей.


T>>char b[flag<int>::IsTrue == 1 ? 1 : -1];//1 — вот здесь комо валится


R>Всё правильно валится, он то как раз по стандарту всё делает.


R>


Дело в том, что раз Comeau работает по стандарту, значит, он должен найти

yes flag<int,no,-1>::check(flag<flag_type,no,-1>&,type&);


Он там точно есть. Если ADL не должен находить его — то что же вообще он должен находить? Это ведь именно тот же самый тип!

<вырезано, дабы сохранить место на сервере>
Re[4]: Объясняю ещё раз
От: Erop Россия  
Дата: 21.06.07 15:14
Оценка:
Здравствуйте, tilarids, Вы писали:


T>...Мне хочется, чтобы если где-нибудь, или когда-нибудь участвовал некий специально сформированный шаблон, то автоматически где-нибудь некая сущность это в себе хранила. Что-то вроде:


Ну для этого ADL вроде как подходит...

Хотя всё равно только в пределах единицы трансляции. А что будет с базой шаблонов --
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Объясняю ещё раз
От: tilarids Украина tilarids.blogspot.com
Дата: 23.06.07 03:15
Оценка:
Здравствуйте, Erop, Вы писали:

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



T>>...Мне хочется, чтобы если где-нибудь, или когда-нибудь участвовал некий специально сформированный шаблон, то автоматически где-нибудь некая сущность это в себе хранила. Что-то вроде:


E>Ну для этого ADL вроде как подходит...


E>Хотя всё равно только в пределах единицы трансляции. А что будет с базой шаблонов --


Переписал все заново — теперь все выглядит намного проще. Чистый код:


namespace compile_time_flag
{
    struct no{char _no[1];};
    struct yes{char _yes[2];};

    no check(...);

    template <class T> T& make_ref();
    template <class T> T* make_ptr();

    template <class T>
    struct B
    {
    };

    template <class T>
    struct A
    {
        static void foo(){};
        friend yes check(B<T>&);
    };

#define CHECK(x) (sizeof(check(make_ref< B< x > >())) - 1)
#define INIT(x) A< x >::foo()
}


Simple usage:

int main()
{
    using namespace compile_time_flag;
    static const int j = CHECK(int);
    INIT (int);
    static const int i = CHECK(int);
    char b[i!=j?1:-1];
    (void)b;
    return 0;
}


Some more files:

"RealWorker.h"
#pragma once
#include <iostream>

class CRealWorker
{
public:
    CRealWorker(void);
    ~CRealWorker(void);
    void Work()
    {
        std::cout<<"Real work goes here!!!\n";
    }
};


"DummyWorker.h"
#pragma once
#include <iostream>
class CDummyWorker
{
public:
    CDummyWorker(void);
    ~CDummyWorker(void);
    void Work()
    {
        std::cout<<"Just relaxing :)\n";
    }
};


"Worker1.h"
#pragma once
#include "DummyWorker.h"
#include "RealWorker.h"
#include "compile_time_flag.h"
template <int value>
class CWorker1;

template <>
class CWorker1<0> : public CDummyWorker
{
};

template <>
class CWorker1<1> : public CRealWorker
{
};

struct Worker{};
#define CWorker CWorker1< CHECK(Worker) >
#define InitWorker() INIT(Worker)


Usage:

int main()
{
    using namespace compile_time_flag;
    CWorker w1;
    InitWorker();
    CWorker w2;

    w1.Work();//dummy
    w2.Work();//work
    return 0;
}


Как видно, использовать можно как и в простых случаях, так и в более сложных структурах. Естественно, с большой уверенностью, что именно ты делаешь

И самое приятное. Компилируется и работает в VC8, а также в Comeau Online и здесь в MINGW/C++ и EDG/C++.
PS. Проверял только Simple usage в онлайн компайлерах, по причинам вполне понятным
Re[6]: Объясняю ещё раз
От: Programador  
Дата: 23.06.07 20:16
Оценка:
Здравствуйте, tilarids, Вы писали:

T>Переписал все заново — теперь все выглядит намного проще. Чистый код:



T>
T>namespace compile_time_flag
T>{
T>    struct no{char _no[1];};
T>    struct yes{char _yes[2];};

T>    no check(...);

T>    template <class T> T& make_ref();
T>    template <class T> T* make_ptr();

T>    template <class T>
T>    struct B
T>    {
T>    };

T>    template <class T>
T>    struct A
T>    {
T>        static void foo(){};
T>        friend yes check(B<T>&);
T>    };

T>#define CHECK(x) (sizeof(check(make_ref< B< x > >())) - 1)
T>#define INIT(x) A< x >::foo()
T>}
T>


T>Simple usage:


T>
T>int main()
T>{
T>    using namespace compile_time_flag;
T>    static const int j = CHECK(int);
T>    INIT (int);
T>    static const int i = CHECK(int);
T>    char b[i!=j?1:-1];
T>    (void)b;
T>    return 0;
T>}
T>

Двухфазный механизм возможно дает тоже. Не сообрауже сразу чем бинарный CHECK INIT может быть лучше.
Можно еще очистить этот код, чтоб вообще никакой магии не было

namespace compile_time_flag
{
    struct no{char _no[1];};
    struct yes{char _yes[2];};

    no check(...);

    template <class T>
    struct A
    {
    };

#define CHECK(x) (sizeof(check( A< x >())) - 1)
#define INIT(x) yes check(const A<x>&);
}
Re[7]: Объясняю ещё раз
От: Аноним  
Дата: 23.06.07 21:39
Оценка:
namespace compile_time_flag
{
    struct no{char _no[1];};
    struct yes{char _yes[2];};

    no check(...);
#define CHECK(x) (sizeof(check( A< x >())) - 1)
#define INIT(x) yes check(const A<x>&);

    template <class T>
    struct A
    {friend INIT(T)
    };

}

int main()
{
    using namespace compile_time_flag;
    static const     int k = CHECK(int);
    static const     int j = CHECK(int);
    //INIT (int);
    static const     int i = CHECK(int);

    char b[k!=j?1:-1];
    //(void)b;
    char cc[11]={k,j,i};
    (void)cc;
    return 0;
}
Re[6]: А чего бы совместимо-то не сделать?
От: Erop Россия  
Дата: 24.06.07 05:23
Оценка:
Здравствуйте, tilarids, Вы писали:

T>
T>int main()
T>{
T>    using namespace compile_time_flag;
T>    static const int j = CHECK(int);
T>    INIT (int);
T>    static const int i = CHECK(int);
T>    char b[i!=j?1:-1];
T>    (void)b;
T>    return 0;
T>}
T>


Ну типа A<int> -- локальный класс?
По идее, если по стандарту, то POI A<int> должно бы быть до функции main, так как A<int> вроде как с внешним связыванием...

T>PS. Проверял только Simple usage в онлайн компайлерах, по причинам вполне понятным

ИМХО в любой момент могёт рвануть....

Ну и главное, можно проще намного сделать.
Типа так:

namespace compile_time_flag
    struct no{char _no[1];};
    struct yes{char _yes[2];};

    template<typename T>
    const T* get_ptr();

} // compile_time_flag

compile_time_flag::no compile_time_flag_check(...);

#define _INIT_( id_type ) extern compile_time_flag::yes compile_time_flag_check( const id_type* )
#define IN_CLASS_INIT( id_type ) friend _INIT_( id_type ) 
#define INIT( id_type ) extern _INIT_( id_type ) 
#define CHECK( id_type ) ( sizeof( compile_time_flag_check( compile_time_flag::get_ptr<id_type>() ) ) \
    == sizeof( compile_time_flag::yes ) )
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Невероятно, но факт! Не константные значения в компа
От: Programador  
Дата: 24.06.07 13:46
Оценка:
Здравствуйте, tilarids, Вы писали:

T>Ну, это стандартом не оговорено, кажется, — что должно происходить вначале — подсчёт дефолтовых параметров, или включение в loookup всех внутренних функций. Если оговорено — цитату, пожалуйста. А то Comeau пока в меньшинстве — мне более логичным на моем примере кажется поведение именно всех остальных компиляторов(точнее, поведение на нем студии )


Согласен — нормальное поведение компиляторов. Все компилирую. Правда VC6 захотел имена в предварительной декларации и енум вместо статик. А Comeau известен своей глючностью

    template <class C1,class C2,int N> struct flag;

    template <class flag_type,class type = yes, ..................
    struct flag
    {
        friend yes check(flag<flag_type,no,-1>&,type&);
        enum {IsTrue = id};
    };
}

Классы разные
int main()
{
    compile_time_flag::flag<float> f0a,f0b;
    compile_time_flag::flag<float> f1a,f1b;
    int idv[]={f0b.IsTrue,f1b.IsTrue}; // разные значения
    f0a=f0b;
    f1a=f1b;
    f0a=f1a; // присваивание невозможно - ошибка
}

В С полно таких мест когда один и тоже код ведет себя по разному в различных местах. А заставлять компилятор лазить внутрь — это превращать его в пролог Поведение компилятора должно быть как можно проще, тогда все предсказуемо будет
Re[10]: Невероятно, но факт! Не константные значения в компа
От: remark Россия http://www.1024cores.net/
Дата: 24.06.07 17:27
Оценка:
Здравствуйте, tilarids, Вы писали:

R>>Да, должен найти, только в обеих случаях, а не только во втором.


T>Ну, это стандартом не оговорено, кажется, — что должно происходить вначале — подсчёт дефолтовых параметров, или включение в loookup всех внутренних функций. Если оговорено — цитату, пожалуйста. А то Comeau пока в меньшинстве — мне более логичным на моем примере кажется поведение именно всех остальных компиляторов(точнее, поведение на нем студии )


Тут дело не в том, что раньше: подсчёт дефолтовых параметров, или включение в loookup всех внутренних функций.
Тут всё проше — если функция может быть найдена, то она должна быть найдена.
Ссылку из стандарта ISO привести сложно, т.к. это базовая вещь. Нет какого-то одного абзаца, который конкретно разъяснял всю эту ситуацию. Тут смешано очень много вещей.

Общая идея такая. (Это как раз, то что я пытался опровергнуть, но не получилось. Ну точнее не получилось в соотв. со стандартом ISO, а на большинстве компиляторов как-раз получилось).

У компилятора в процессе компиляции нет контекста (т.е. состояния). Точнее нет изменяемого контекста (т.е. того, на которой может влиять программист). Т.е. у компилятора в каждой точке программы есть один чётко определённый контекст. Соответственно отсюда следует, что в принципе не может быть ничего о чём я писал — главное — не может быть "переменных", т.е. одно и тоже выражение в одном и том же контексте (читай — месте программы) не может иметь разных значений. И в этом принципиальное отличие от "ран-тайм".


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Объясняю ещё раз
От: remark Россия http://www.1024cores.net/
Дата: 25.06.07 08:11
Оценка:
Здравствуйте, tilarids, Вы писали:

T>И самое приятное. Компилируется и работает в VC8, а также в Comeau Online


Ты попробуй Comeau Online не с dinkumware, а который они сами предлагают. На dinkumware старая версия, а они похоже это исправляли как раз недавно.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Объясняю ещё раз
От: tilarids Украина tilarids.blogspot.com
Дата: 26.06.07 11:21
Оценка:
Здравствуйте, remark, Вы писали:

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


T>>И самое приятное. Компилируется и работает в VC8, а также в Comeau Online


R>Ты попробуй Comeau Online не с dinkumware, а который они сами предлагают. На dinkumware старая версия, а они похоже это исправляли как раз недавно.


R>


Проверял здесь . Кажется, официальный вариант Если же имеется ввиду оффлайн компайлер+линкер — то на него я денег не имею

В общем, нити, повторное обсуждение в которых я спровоцировал , можно считать закрытыми. Действительно, такой трюк скорее восстает не против стандарта, а против здравого смысла. Кроме того, для себя я понял, что Comeau не так хорош в поддержке стандарта, как его рисуют(как, в принципе и остальные компиляторы — но это не мешает им работать).

Теперь осталось найти язык, сходный с С++ по системным возможностям(а лучше — позволяющий использовать С++ конструкции в каком-либо удобном виде).
<вырезано, дабы сохранить место на сервере>
Re[8]: Объясняю ещё раз
От: remark Россия http://www.1024cores.net/
Дата: 26.06.07 11:48
Оценка:
Здравствуйте, tilarids, Вы писали:

T>Проверял здесь . Кажется, официальный вариант Если же имеется ввиду оффлайн компайлер+линкер — то на него я денег не имею


Ну так и чего на нём? Работает или нет? В смысле, наверное правильнее спрашивать, как работает?

T>В общем, нити, повторное обсуждение в которых я спровоцировал , можно считать закрытыми. Действительно, такой трюк скорее восстает не против стандарта, а против здравого смысла. Кроме того, для себя я понял, что Comeau не так хорош в поддержке стандарта, как его рисуют(как, в принципе и остальные компиляторы — но это не мешает им работать).


А чем Comeau не соотв. стандарту? Как раз вроде он один и соотв.

T>Теперь осталось найти язык, сходный с С++ по системным возможностям(а лучше — позволяющий использовать С++ конструкции в каком-либо удобном виде).


D?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: Объясняю ещё раз
От: Erop Россия  
Дата: 26.06.07 12:26
Оценка:
Здравствуйте, tilarids, Вы писали:

T>...такой трюк скорее восстает не против стандарта, а против здравого смысла.

Ну связь здравого смысла и стандарта С++ темна для меня. Но мне таки кажется, что такой трюк не должен работать именно по стандарту. Или укажи таки POI задействованных шаблонов

И главное, чем тебе просто объявлять функцию какого-то прототипа, в макросе INIT не нравится? Всё по стандарту, без хаков и надёжно вроде...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Объясняю ещё раз
От: Programador  
Дата: 26.06.07 12:50
Оценка:
Здравствуйте, remark, Вы писали:

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


T>>Проверял здесь . Кажется, официальный вариант Если же имеется ввиду оффлайн компайлер+линкер — то на него я денег не имею


R>Ну так и чего на нём? Работает или нет? В смысле, наверное правильнее спрашивать, как работает?


Интересно как именно он работает
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&);
        enum { IsTrue = id};
    };
}


int main()
{
    compile_time_flag::flag<float> f0a,f0b;
    compile_time_flag::flag<float> f1a,f1b;
    int idv[]={f0b.IsTrue,f1b.IsTrue}; // разные значения
    f0a=f0b;
    f1a=f1b;
    f0a=f1a;  //присваивание разных инстанций - ошибка в VC8 ok Comeau
}

У VC8 первая переменная типа <.., no, 0> вторая типа <.., no, 1> у Comeau одног. Интересно какого?
Re[10]: Объясняю ещё раз
От: Programador  
Дата: 26.06.07 14:23
Оценка:
Произвел исследование все выяснил
namespace compile_time_flag
{
    struct yes{} dyes;
    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&);
        // отсюда начинается видимость yes check
        enum { IsTrue = id};
    };
    //  yes check(flag<float,no,-1>&,yes&);
    //  это таки ломает его
}
using namespace compile_time_flag;

int main()
{   compile_time_flag::flag<float,compile_time_flag::yes,0> d0;
    compile_time_flag::flag<float,compile_time_flag::no,-1> f0;

    yes yy=check(f0,dyes);
    //  здесь  yes check точно видна во время исполнения 
    compile_time_flag::flag<float> f0a,f0b;
    compile_time_flag::flag<float> f1a,f1b;
    int idv[]={f0b.IsTrue,f1b.IsTrue}; 
    f0a=f0b;
    f1a=f1b;
    
    d0=f0a; // проверяем что  f0a типа compile_time_flag::flag<float,compile_time_flag::yes,0> 
        //  поскольку 0 yes check()   не учлась в шаблон, тоесть не видна
    f0a=f1a; // второй compile_time_flag::flag<float> тотже, тоесть с 0
}

namespace compile_time_flag
{ //   сама функция
  yes check(flag<float,no,-1>&,yes&)
  { return dyes;
  }
}

Получаетс следующая картина деклараци френд делает функцию доступной для непосредственного вызова, но недоступной для шаблонов. Явное противоречие.
Комеау опять не со всеми, правда обычно он отказывается когда должен,
сейчас скомпилил когда не должен


void f(int);
f(1.);
void f(double);
f(1.);

Такой код никого не удивляет. Здесь аналогично. compile_time_flag::flag<float> должны быть 2 разных класса
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.