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 — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
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[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[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...
Пока на собственное сообщение не было ответов, его можно удалить.