Есть шаблон класса, у которого имеется статический элемент-данные:
// file Foo.htemplate <class T>
class Foo
{
public:
static T * member;
/* Другие элементы*/
};
template <class T>
T * Foo<T>::member = NULL;
Где будет размещаться Foo<someType>::member, если Foo.h включить в два файла и инстанцировать шаблон с одним и тем же типом someType? Будет ли память выделяться дважды? как это зависит от компилятора? что говорится по этому поводу в стандарте?
Здравствуйте, Анатолий Широков, Вы писали:
АШ>Здравствуйте, Эдик, Вы писали:
Э>>Здравствуйте все!
Э>>Есть шаблон класса, у которого имеется статический элемент-данные:
АШ>см. 14.5.1.3 п.1.
Да, если стандарт не доступен, то подобное определение разрешено стандартом.
Re[2]: Статические элементы-данные шаблонных классов
Здравствуйте, Анатолий Широков, Вы писали:
Э>>Есть шаблон класса, у которого имеется статический элемент-данные:
АШ>см. 14.5.1.3 п.1.
Насколько я понимаю, там описано, где можно определять статические данные. Про то, как они будут созданы, ничего не сказано.
Re[3]: Статические элементы-данные шаблонных классов
Здравствуйте, Вадим Никулин, Вы писали:
ВН>Здравствуйте, Анатолий Широков, Вы писали:
Э>>>Есть шаблон класса, у которого имеется статический элемент-данные:
АШ>>см. 14.5.1.3 п.1. ВН>Насколько я понимаю, там описано, где можно определять статические данные. Про то, как они будут созданы, ничего не сказано.
Раз сказано, что можно таким образом определять статический член шаблона класса, то разумно предположить, что компилятор позаботися о размещении как специализации класса, так и его статических членов.
Re[3]: Статические элементы-данные шаблонных классов
Здравствуйте, Вадим Никулин, Вы писали:
АШ>>см. 14.5.1.3 п.1. ВН>Насколько я понимаю, там описано, где можно определять статические данные. Про то, как они будут созданы, ничего не сказано.
А сказано об этом в 3.2.5:
If the definitions of D satisfy all these requirements, then program shall behave as if there were a single definition of D.
Re[4]: Статические элементы-данные шаблонных классов
Здравствуйте, Анатолий Широков, Вы писали:
АШ>>>см. 14.5.1.3 п.1. ВН>>Насколько я понимаю, там описано, где можно определять статические данные. Про то, как они будут созданы, ничего не сказано.
АШ>Раз сказано, что можно таким образом определять статический член шаблона класса, то разумно предположить, что компилятор позаботися о размещении как специализации класса, так и его статических членов.
Вопрос был именно о том, сколько будет объектов создано. Напомню:
"...Будет ли память выделяться дважды? как это зависит от компилятора? что говорится по этому поводу в стандарте?..."
Re[5]: Статические элементы-данные шаблонных классов
ВН>Вопрос был именно о том, сколько будет объектов создано. Напомню: ВН>"...Будет ли память выделяться дважды? как это зависит от компилятора? что говорится по этому поводу в стандарте?..."
Согласен, ваша ссылка отвечает именно на эти вопросы, я же сделал логическое заключение по первоначальной ссылке.
Re[4]: Статические элементы-данные шаблонных классов
Hello, Вадим!
You wrote on Tue, 21 Sep 2004 11:09:11 GMT:
ВН> Здравствуйте, Вадим Никулин, Вы писали:
АШ>>> см. 14.5.1.3 п.1. ВН>> Насколько я понимаю, там описано, где можно определять статические ВН>> данные. Про то, как они будут созданы, ничего не сказано.
ВН> А сказано об этом в 3.2.5: ВН> If the definitions of D satisfy all these requirements, then program ВН> shall behave as if there were a single definition of D.
Еще, в некоторых компиляторах это можно настраивать.
Э>Где будет размещаться Foo<someType>::member, если Foo.h включить в два файла и инстанцировать шаблон с одним и тем же типом someType? Будет ли память выделяться дважды? как это зависит от компилятора? что говорится по этому поводу в стандарте?
На практике компилятор при компиляции каждой единицы трансляции, в которой инстантинируется Foo<T>::member, сгенерирует секцию данных для Foo<T>::member. Но эти секции будут помечены атрибутом linkonce (или чем-то аналогичным). В дальнейшем линкер при сборке программы оставит только одну из этих секций, а дубли сбросит.
Аналогичный механизм применяется при обработке inline-функций и таблиц виртуальных методов.
Шахтер:
> Э>Где будет размещаться Foo<someType>::member, если Foo.h включить в два файла и инстанцировать шаблон с одним и тем же типом someType? Будет ли память выделяться дважды? как это зависит от компилятора? что говорится по этому поводу в стандарте?
> На практике компилятор при компиляции каждой единицы трансляции, в которой инстантинируется Foo<T>::member, сгенерирует секцию данных для Foo<T>::member. Но эти секции будут помечены атрибутом linkonce (или чем-то аналогичным). В дальнейшем линкер при сборке программы оставит только одну из этих секций, а дубли сбросит.
Это один из возможных сценариев. Другой может заключаться, например, в добавлении специального шага между компиляцией и компоновкой, во время которого и будет производиться инстанцирование. Есть и другие варианты.
Posted via RSDN NNTP Server 1.9 gamma
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: Статические элементы-данные шаблонных классов
Здравствуйте, Шахтер, Вы писали:
Ш>На практике компилятор при компиляции каждой единицы трансляции, в которой инстантинируется Foo<T>::member, сгенерирует секцию данных для Foo<T>::member. Но эти секции будут помечены атрибутом linkonce (или чем-то аналогичным). В дальнейшем линкер при сборке программы оставит только одну из этих секций, а дубли сбросит. Ш>Аналогичный механизм применяется при обработке inline-функций и таблиц виртуальных методов.
Значит, получается, что все модули, инстанцирующие одинаковые шаблоны (с одинаковыми же параметрами) д.быть скомпилированы с одинаковыми опциями ? (ну, там, соглашения о вызовах и т.п.) Иначе, исходя из предыдущего утверждения, это будут разные инстанации шаблона.
Re[3]: Статические элементы-данные шаблонных классов
Здравствуйте, s.ts, Вы писали:
ST>Здравствуйте, Шахтер, Вы писали:
Ш>>На практике компилятор при компиляции каждой единицы трансляции, в которой инстантинируется Foo<T>::member, сгенерирует секцию данных для Foo<T>::member. Но эти секции будут помечены атрибутом linkonce (или чем-то аналогичным). В дальнейшем линкер при сборке программы оставит только одну из этих секций, а дубли сбросит. Ш>>Аналогичный механизм применяется при обработке inline-функций и таблиц виртуальных методов.
ST>Значит, получается, что все модули, инстанцирующие одинаковые шаблоны (с одинаковыми же параметрами) д.быть скомпилированы с одинаковыми опциями ? (ну, там, соглашения о вызовах и т.п.) Иначе, исходя из предыдущего утверждения, это будут разные инстанации шаблона.
и как должен по стандарту вести себя компилятор/компоновщик ?
Я вижу 2 варианта:
-=- ощибка : не разрешенные ссылки
-=- разные инстанции шаблонов для модулей с различными опциями компиляции
Re[5]: Статические элементы-данные шаблонных классов
Здравствуйте, s.ts, Вы писали:
ST>Здравствуйте, Шахтер, Вы писали:
Ш>>Да. Иначе получится тонкое нарушение ODR.
ST>что есть ODR ?
One definition rule. Если кратко, то это правило языка, которое требует одного определения любой сущности в программе, либо, в тех случаях, когда невозможно избежать многократного определения их эквивалентности. Посмотри Вандерворда и Джосстаиса "Шаблоны C++", там в конце есть приложение с разяснениями и примерами.
ST>и как должен по стандарту вести себя компилятор/компоновщик ?
Нарушения ODR далеко не всегда диагностируются. Только в наиболее простейших случаях.
ST>Я вижу 2 варианта: ST>-=- ощибка : не разрешенные ссылки ST>-=- разные инстанции шаблонов для модулей с различными опциями компиляции
К сожалению, практическая реализация нарушения всех, включая самые тонкие случаи ODR слишком накладна или даже невозможна.
Шахтер:
> ST>и как должен по стандарту вести себя компилятор/компоновщик ? > > Нарушения ODR далеко не всегда диагностируются. Только в наиболее простейших случаях.
А в сложных это стоит дорого. Скажем, EDG потратили около года на реализацию диагностики нарушений ODR, включая рефакторинг имевшегося кода компилятора. Разработчики VC++ говорили, что следующая версия будет диагностировать намного больше нарушений ODR, чем 7.1.
Posted via RSDN NNTP Server 1.9 gamma
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[7]: Статические элементы-данные шаблонных классов
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Шахтер:
>> ST>и как должен по стандарту вести себя компилятор/компоновщик ? >> >> Нарушения ODR далеко не всегда диагностируются. Только в наиболее простейших случаях.
ПК>А в сложных это стоит дорого. Скажем, EDG потратили около года на реализацию диагностики нарушений ODR, включая рефакторинг имевшегося кода компилятора. Разработчики VC++ говорили, что следующая версия будет диагностировать намного больше нарушений ODR, чем 7.1.
А у меня, кстати, вопрос есть на эту тему.
const int IntConst=12345;
inline void Fun( void (*f)(const int &) ) { f(IntConst); }
Вот такая последовательность деклараций, помещённая в заголовочный файл, который в свою очередь включен в несколько единиц трансляции.
Есть ли здесь прямое нарушение ODR, или такое нарушение только потенциальное?
Здравствуйте, Шахтер, Вы писали:
Ш>А у меня, кстати, вопрос есть на эту тему.
Ш>
Ш>const int IntConst=12345;
Ш>inline void Fun( void (*f)(const int &) ) { f(IntConst); }
Ш>
Ш>Вот такая последовательность деклараций, помещённая в заголовочный файл, который в свою очередь включен в несколько единиц трансляции. Ш>Есть ли здесь прямое нарушение ODR, или такое нарушение только потенциальное?
А я вообще тут никаких нарушений не вижу. Defination происходит только один раз (учитывая internal linkage), а что ты делаешь со значением в run-time — это твое дело и никакого отношения к ODR оно, ИМХО, не имеет...
Или я "соль" не почувствовал?
... << RSDN@Home 1.1.4 @@subversion >>
лэт ми спик фром май харт
Re[9]: Статические элементы-данные шаблонных классов
Ш>>const int IntConst=12345;
Ш>>inline void Fun( void (*f)(const int &) ) { f(IntConst); }
Ш>>
Ш>>Вот такая последовательность деклараций, помещённая в заголовочный файл, который в свою очередь включен в несколько единиц трансляции. Ш>>Есть ли здесь прямое нарушение ODR, или такое нарушение только потенциальное?
V>А я вообще тут никаких нарушений не вижу. Defination происходит только один раз (учитывая internal linkage), а что ты делаешь со значением в run-time — это твое дело и никакого отношения к ODR оно, ИМХО, не имеет... V>Или я "соль" не почувствовал?
Соль в том, что функция Fun в разных единицах трансляции будет передавать в качестве аргумента ссылку на разные IntConst.
Собственно на вопрос Шахтера ответить не могу, но чтобы пресечь возможность подобных фокусов с const integral, иногда лучше использовать enum.
Здравствуйте, Шахтер, Вы писали:
Ш>А у меня, кстати, вопрос есть на эту тему.
Ш>
Ш>const int IntConst=12345;
Ш>inline void Fun( void (*f)(const int &) ) { f(IntConst); }
Ш>
Ш>Вот такая последовательность деклараций, помещённая в заголовочный файл, который в свою очередь включен в несколько единиц трансляции.
Ш>Есть ли здесь прямое нарушение ODR, или такое нарушение только потенциальное?
По-моему, 3.2(5) достаточно ясно отвечает на этот вопрос: здесь есть нарушение ПОО.
...
— в каждом определении D соответственные имена будут, по результатам сопоставления в соответствии с §3.4, отсылать к сущности, определенной внутри определения D, или к одной и той же сущности по результатам разрешения перегрузки имени (§13.3) и после подбора частичной специализации шаблона (§14.8.3), за исключением того, что имя может отсылать к константному (const) объекту со внутренней компонуемостью или без компонуемости, если последний имеет один и тот же целочисленный или перечислимый тип во всех определениях D, определен при помощи константного выражения (§5.19) и используется значение (но не адрес) этого объекта и значение объекта одинаково во всех определениях D...
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.