Здравствуйте, Константин Л., Вы писали:
КЛ>как я понял каждое выражение magic<>::val должно инстанциировать magic заново и sizeof(engine(*(magicc*)0, *(type*)0)) выдавать новые значение? КЛ>Все равно не очень понятно
Если на пальцах, то примерно так:
При каждом упоминании magic<>::val заного вычисляется значение аргумента по-умолчанию, причём вычисляется оно именно в той точке, где написано magic<>::val.
И выдаёт это вычисление разные результаты, т.к. предыдущая специализация magic внесла новую перегрузку функции engine.
Как-то так...
Здравствуйте, 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]: Невероятно, но факт! Не константные значения в компай
Здравствуйте, remark, Вы писали:
R>Не понял мысль. R>По-моему, эта цитата подтверждает работоспособность моего кода. R>Да, я объявляю все дружественные функции в глобальном пространстве имён. Всё правильно. R>Да, потом я её нахожу, т.к. тип параметра функции есть сам этот класс (если быть совсем точным, то не сам этот класс, а другая специализация этого же шаблона, но касательно областей видимости имён это ничего не меняет).
R>
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, Вы писали:
R>>Пришло время очередного ресёрча
Ш>Хочу влить свою бочку дегтя в эту ложку сахарного сиропа.
Ш>1) Я пока не увидел доказательства того, что это standard-compliant поведение. По-моему -- баг.
Какие моменты у тебя вызывают недоверие?
Ш>2) Если это не баг, то это дыра в стандарте. Срочно фиксить стандарт.
Почему?
Ш>3) Пользоваться такими изобретениями в реальной работе категорически нельзя. Ломиком по рукам.
С такими тезисами обращайся в Философию, там можно такое обсудить на пару сотен постов Или лучше сразу в холивары Покрайней мере к С++ это отношения не имеет.
Здравствуйте, 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() видно только форвард объявление класса...
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 выдал пару вполне законных варнингов, но они не то что бы особо принципиальные. Если они тебе сильно мешают — можешь их пофиксить...
Здравствуйте, Pavel Chikulaev, Вы писали:
PC>Здравствуйте, remark, Вы писали:
R>>Не понял мысль. R>>По-моему, эта цитата подтверждает работоспособность моего кода. R>>Да, я объявляю все дружественные функции в глобальном пространстве имён. Всё правильно. R>>Да, потом я её нахожу, т.к. тип параметра функции есть сам этот класс (если быть совсем точным, то не сам этот класс, а другая специализация этого же шаблона, но касательно областей видимости имён это ничего не меняет).
R>>
PC>Объясню на примере IROVа http://rsdn.ru/Forum/Message.aspx?mid=2338001&only=1
Во-первых, тут ошибка, т.к. friend engine() не должна находится без ADL, т.е. это бы при любом раскладе не стало бы работать. Но это так мелочи.
PC>friend int engine(_true); в magic<int> объявляет функцию в глобальном пространстве еще до инстанирования шаблона согласно 7.3.1.2/3, поэтому код абсолютно равнозначен этому: PC>
Нет, это абсолютно не равнозначно.
PC>Именно поэтому на комо это не работает. В VC же баг, там он действительно добавляется лишь после инстанцирования.
Подсказка 1.
template<typename type>
struct magic
{
friend int engine(type);
};
Сколько это определение шаблонного класса должно _сразу_ вынести функций в глобальное пространство имён? Для всего бесконечного возможного набора типов, которыми когда-либо могут параметризовать этот шаблон?
Подсказка 2.
Подумай о POI. Когда в первый раз компилятор начинает компилировать специализацию шаблона. И когда он действительно видет, что какую-то функцию надо выносить в глобальное пространство, и видит какую именно. До POI, т.е. пока не требуется определения класса, компилятор не то что не обязан, он не может компилировать специализацию.
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]: Невероятно, но факт! Не константные значения в компай
Здравствуйте, 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
R>Сколько это определение шаблонного класса должно _сразу_ вынести функций в глобальное пространство имён? Для всего бесконечного возможного набора типов, которыми когда-либо могут параметризовать этот шаблон?
Да именно так, т.е. равнозначно этому (кроме прав доступа)
template<typename type>
int engine(type);
template<typename type>
struct magic
{
};
R>Подумай о POI. Когда в первый раз компилятор начинает компилировать специализацию шаблона. И когда он действительно видет, что какую-то функцию надо выносить в глобальное пространство, и видит какую именно. До POI, т.е. пока не требуется определения класса, компилятор не то что не обязан, он не может компилировать специализацию.
Это единственное исключение, но это так, т.е. компилятор должен пропускать все в шаблоне кроме друзей.
Re[5]: Невероятно, но факт! Не константные значения в компай
Здравствуйте, 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];
^
Уж вот этому точно не равнозначно. Однозначно.
Тут шаблонная функция, а у меня не шаблонная. А это две большие разницы.
R>>Подумай о POI. Когда в первый раз компилятор начинает компилировать специализацию шаблона. И когда он действительно видет, что какую-то функцию надо выносить в глобальное пространство, и видит какую именно. До POI, т.е. пока не требуется определения класса, компилятор не то что не обязан, он не может компилировать специализацию. PC>Это единственное исключение, но это так, т.е. компилятор должен пропускать все в шаблоне кроме друзей.
А можно ссылку на стандарт или ещё куда-то?
А если друг в шаблонном клсее, который вложен в другой шаблонный класс???... Ему придётся компилировать ещё и вложенный шаблонный класс??? ... Если вложенный шаблонный класс как-то хитро зависит от параметров шаблона объемлющего?...
Не очень понятно, как это должно/может работать...
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Аноним, Вы писали:
А>>Я думаю, Комо, а скорее всего, последний фронт-энд от едг (у Комо он какой-то древний уже). Уж если ЕДГ и глючит, то в совсем уж нетривиальных моментах. А>>Автор упомянул ЕДГ, но я не понял, что это значит — купить его простым смертным — малореально
R>EDG C++ это компилирует R>здесь
R>
Хехе, у них версия фронт-энда старее, чем у Комо онлайн.
Of course, the code must be complete enough to compile and link.
Re[3]: Невероятно, но факт! Не константные значения в компай
Здравствуйте, remark, Вы писали:
NB>>вопрос по выделенному. при замене *(magicc*)0 на magicc() получаем одинаковые magic<>::val. NB>>чем вызвано?
R>Чем компилил?
гсс 3.4
R>Это вообще не должно компилироваться, т.к. ты пытаешься сделать вызов конструктора до определения класса. Там, где ты написал magicc() видно только форвард объявление класса...
а не при создании первой переменной?
Re[3]: Невероятно, но факт! Не константные значения в компай
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, remark, Вы писали:
R>>Здравствуйте, Шахтер, Вы писали:
Ш>>>Здравствуйте, remark, Вы писали:
R>>>>Пришло время очередного ресёрча
Ш>>>Хочу влить свою бочку дегтя в эту ложку сахарного сиропа.
Ш>>>1) Я пока не увидел доказательства того, что это standard-compliant поведение. По-моему -- баг.
R>>Какие моменты у тебя вызывают недоверие?
А>Для начала — разыменование нулевого указателя.
Пуристы могут заменить это разыменование на вызов функции:
magicc& get_some_magic();
R>>Почему?
А>Ты что, серьезно считаешь, что поиск имен зависит от того, что было инстанцировано, а что нет?
Я серьёзно считаю, что поиск имён зависит от того, что видно в POI.
Ш>>>3) Пользоваться такими изобретениями в реальной работе категорически нельзя. Ломиком по рукам.
R>>С такими тезисами обращайся в Философию, там можно такое обсудить на пару сотен постов Или лучше сразу в холивары Покрайней мере к С++ это отношения не имеет.
А>Код с UB уже тоже.