Здравствуйте, Аноним, Вы писали:
А>Занятная штука:
А>template<typename T> А>class counter{ А> static <b>T</b> cnt; А>public: А> counter(){ А> cnt++; А> }
А> ~counter(){ А> cnt--; А> } А>};
А>template<typename T> А><b>int</b> counter<T>::cnt = 0;
А>В функции main: А>counter<int> i; А>counter<int> j;
А>counter<float> f; //Понятно, ошибка C2371: 'cnt' : redefinition; different basic types
обращаем внимание на выделенный текст и все действительно становится понятным...
А>Так как быть с шаблонными классами и статическими элементами??
думается мне счеткик таки должен быть int... в таком случае все работает...
Здравствуйте, zaufi, Вы писали:
Z>Здравствуйте, Аноним, Вы писали:
А>>Занятная штука:
А>>template<typename T> А>>class counter{ А>> static T cnt; А>>public: А>> counter(){ А>> cnt++; А>> }
А>> ~counter(){ А>> cnt--; А>> } А>>};
А>>template<typename T> А>>[b]int[/b>]counter<T>::cnt = 0;
А>>В функции main: А>>counter<int> i; А>>counter<int> j;
А>>counter<float> f; //Понятно, ошибка C2371: 'cnt' : redefinition; different basic types Z>обращаем внимание на выделенный текст и все действительно становится понятным...
непрально выделел текст ))
А>>Так как быть с шаблонными классами и статическими элементами?? Z>думается мне счеткик таки должен быть int... в таком случае все работает...
собственно даже если счетчик буит иметь тип T все также буит работать...
это плохо без особой нужды использовать статические в функции. Это всё равно что добавить if (true) который никогда не вырежит компилятор. И должно быть оправдание для такого действия.
Здравствуйте, Caracrist, Вы писали:
C>Здравствуйте, ffk, Вы писали:
ffk>>Здравствуйте, Аноним, Вы писали:
А>>>Занятная штука:
А>>>template<typename T> А>>>class counter{ А>>> //static T cnt; А>>>public: А>>> counter(){ А>>> cnt()++; А>>> }
А>>> ~counter(){ А>>> cnt()--; А>>> } A>>>private: A>>> int& cnt() {static int cnt_ = 0; return cnt;} ffk>>А>};
C>это плохо без особой нужды использовать статические в функции. Это всё равно что добавить if (true) который никогда не вырежит компилятор. И должно быть оправдание для такого действия.
В 99.99% это пофиг, даже не заметешь.
Критикуешь, предложи более красивое решение.
Здравствуйте, ffk, Вы писали:
ffk>Здравствуйте, Caracrist, Вы писали:
ffk>В 99.99% это пофиг, даже не заметешь. ffk>Критикуешь, предложи более красивое решение.
template<typename T>
class counter{
static int cnt;public:
counter(){
cnt++;
}
~counter(){
cnt--;
}
// тут гдето должны быть публичные функции или friends иначе этот счётчик никогда никто не прочтёт
};
template<typename T>
int counter<T>::cnt = 0;
Здравствуйте, Caracrist, Вы писали:
C>в целом оно выглядит вот так: C>
C>template<typename T>
C>class counter{
C>static int cnt;
C>public:
C>counter(){
C>cnt++;
C>}
C>~counter(){
C>cnt--;
C>}
C>// тут гдето должны быть публичные функции или friends иначе этот счётчик никогда никто не прочтёт
C>};
C>template<typename T>
C>int counter<T>::cnt = 0;
C>
C>простота залог успеха
Насколько успешно такой хидер может быть включён в несколько единиц трансляции? Без использования __declspec(selectany)
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
C>>template<typename T>
C>>class counter{
C>>static int cnt;
C>>public:
C>>counter(){
C>>cnt++;
C>>}
C>>~counter(){
C>>cnt--;
C>>}
C>>// тут гдето должны быть публичные функции или friends иначе этот счётчик никогда никто не прочтёт
C>>};
C>>template<typename T>
C>>int counter<T>::cnt = 0;
C>>
C>>простота залог успеха
GN>Насколько успешно такой хидер может быть включён в несколько единиц трансляции? Без использования __declspec(selectany)
PUBLIC ?f@@YAPAXXZ ; f
; Function compile flags: /Odtp
; File t2.cpp
_TEXT SEGMENT
_p$ = -4 ; size = 4
?f@@YAPAXXZ PROC ; f
; 7 : {
push ebp
mov ebp, esp
sub esp, 8
; 8 : counter <int> c;
; 9 : void* volatile p = &c.cnt;
mov DWORD PTR _p$[ebp], OFFSET ?cnt@?$counter@H@@2HA ; counter<int>::cnt
; 10 : return p;
mov eax, DWORD PTR _p$[ebp]
; 11 : }
mov esp, ebp
pop ebp
ret 0
?f@@YAPAXXZ ENDP ; f
END
Остаётся угадать, что за адреса будут присвоены p в первый и второй разы.
Впринципе, предпосылки для разрешения
template<typename T> int counter<T>::cnt;
понятны, непонятно, почему инстанциация
template<> int counter<int>::cnt;
ведёт себя отлично от 9.4.2/5 (There shall be exactly one definition of a static data member that is used in a program; no diagnostic is required; see 3.2.).
Шаблон класса — семейство классов, а полная специализация не может считаться "отдельным" классом, это всё равно какое-то семейство?
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[8]: Чем статические данные отличаются от методов?
Здравствуйте, gear nuke, Вы писали:
GN>Здравствуйте, Andrew S, Вы писали:
AS>>А что, есть сомнения?
GN>Да, есть. Не могу найти, где это разрешено в Стандарте.
В принципе, есть похожие объекты -- это шаблоны функций и методов. Где, например, написано про них?
GN>
Вообще-то этот код нарушает ODR, так что последствия могут быть любы...
GN>Впринципе, предпосылки для разрешения GN>
GN>template<typename T> int counter<T>::cnt;
GN>
GN>понятны, непонятно, почему инстанциация GN>
GN>template<> int counter<int>::cnt;
GN>
ведёт себя отлично от 9.4.2/5 (There shall be exactly one definition of a static data member that is used in a program; no diagnostic is required; see 3.2.).
А разве в твоём примере была где-то явная инстанциация? А неявные ведут себя не так. Например шаблоны методов ты же описываешь в хедере, рядом с шаблоном класса, и в каждой TU получается своя неявная инстанциация, и ничего, линкуется всё как-то...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Чем статические данные отличаются от методов?
Здравствуйте, Erop, Вы писали:
E>В принципе, есть похожие объекты -- это шаблоны функций и методов. Где, например, написано про них?
Можно иметь 2 копии одной функции и вызывать их из разных мест — наблюдаемое поведение не изменится. Если имеется 2 копии одного объекта, то это подразумевает возможность хранения разных состояний, что и демонстрирует мой пример.
GN>>
E>Вообще-то этот код нарушает ODR, так что последствия могут быть любы...
А чем принципиально этот код отличается от исходного? Тем, что значения разные Обрати внимание на директиву PUBLIC в асм листинге — это внешнее связывание, сохранится если убрать мои изменения.
E>А разве в твоём примере была где-то явная инстанциация?
Не было, но если исправить — результат не изменится.
E> А неявные ведут себя не так. Например шаблоны методов ты же описываешь в хедере, рядом с шаблоном класса, и в каждой TU получается своя неявная инстанциация, и ничего, линкуется всё как-то...
Не пойму, почему проводится аналогия с функциями. Это не первокласные объекты. По-моему аналогия со статическими членами-данными не шаблонных классов более уместна (интуитивна).
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[10]: Чем статические данные отличаются от методов?
Здравствуйте, gear nuke, Вы писали:
GN>Можно иметь 2 копии одной функции и вызывать их из разных мест — наблюдаемое поведение не изменится.
Во-первых, это очень расточительно. Прикинь, весь STL тянулся бы во все TU, например
GN>Если имеется 2 копии одного объекта, то это подразумевает возможность хранения разных состояний, что и демонстрирует мой пример.
Во-вторых, вообще нельзя, так как изменится и наблюдаемое поведение, по крайней мере из-за того, что существуют
1) static in function
2) указатели на функции
E>>Вообще-то этот код нарушает ODR, так что последствия могут быть любы... GN>А чем принципиально этот код отличается от исходного? Тем, что значения разные Обрати внимание на директиву PUBLIC в асм листинге — это внешнее связывание, сохранится если убрать мои изменения.
Тем, что в исходном переменная имеет одно определение...
GN>Не было, но если исправить — результат не изменится.
Ну и так и сяк некорректно всё, потому, что ODR нарушено -- есть несколько неэквивалентных определений одного объекта.
Кроме того, если ты явно инстанцируешь что-то, то, AFAIK, это нужно делать только в одной TU... Так что, по идее, "если исправить", то IMHO, не слинкуется...
E>> А неявные ведут себя не так. Например шаблоны методов ты же описываешь в хедере, рядом с шаблоном класса, и в каждой TU получается своя неявная инстанциация, и ничего, линкуется всё как-то...
GN>Не пойму, почему проводится аналогия с функциями. Это не первокласные объекты. По-моему аналогия со статическими членами-данными не шаблонных классов более уместна (интуитивна).
Зато указатеои на них, вполне себе первоклассные. И гарантируется, что в какой TU указатель на функцию не возьми, во всех совпадут указатели на одну и ту же функцию...
Короче говоря. Определять шаблоном статические переменные -- это общепринято. Так что если это от чего-то не разрешено в стандарте, то это баг стандарта
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Чем статические данные отличаются от методов?
Здравствуйте, gear nuke, Вы писали:
GN>Здравствуйте, Erop, Вы писали:
E>>В принципе, есть похожие объекты -- это шаблоны функций и методов. Где, например, написано про них?
GN>Можно иметь 2 копии одной функции и вызывать их из разных мест — наблюдаемое поведение не изменится.
template<typename T>
struct S
{
void myFunc()
{
static int oproverzhenie;
// blablabla
}
};
Здравствуйте, Erop, Вы писали:
GN>>Можно иметь 2 копии одной функции и вызывать их из разных мест — наблюдаемое поведение не изменится. E>Во-первых, это очень расточительно. Прикинь, весь STL тянулся бы во все TU, например
В случае с функциями транслятор может сравнить например их AST и убрать лишнюю копию.
GN>>Если имеется 2 копии одного объекта, то это подразумевает возможность хранения разных состояний, что и демонстрирует мой пример.
E>Во-вторых, вообще нельзя, так как изменится и наблюдаемое поведение, по крайней мере из-за того, что существуют E>1) static in function E>2) указатели на функции
А зачем они тогда приводились как пример?
E>>>Вообще-то этот код нарушает ODR, так что последствия могут быть любы... GN>>А чем принципиально этот код отличается от исходного? Тем, что значения разные Обрати внимание на директиву PUBLIC в асм листинге — это внешнее связывание, сохранится если убрать мои изменения.
E>Тем, что в исходном переменная имеет одно определение...
Она имеет 2 одинаковых определения в разных TU.
GN>>Не было, но если исправить — результат не изменится. E>Ну и так и сяк некорректно всё, потому, что ODR нарушено -- есть несколько неэквивалентных определений одного объекта. E>Кроме того, если ты явно инстанцируешь что-то, то, AFAIK, это нужно делать только в одной TU... Так что, по идее, "если исправить", то IMHO, не слинкуется...
Слинкуется. Я проверял, ассемблерные листинги не меняются.
E>>> А неявные ведут себя не так. Например шаблоны методов ты же описываешь в хедере, рядом с шаблоном класса, и в каждой TU получается своя неявная инстанциация, и ничего, линкуется всё как-то...
А тут имеет место быть ослабление ODR за счёт inline.
GN>>Не пойму, почему проводится аналогия с функциями. Это не первокласные объекты. По-моему аналогия со статическими членами-данными не шаблонных классов более уместна (интуитивна). E>Зато указатеои на них, вполне себе первоклассные. И гарантируется, что в какой TU указатель на функцию не возьми, во всех совпадут указатели на одну и ту же функцию...
Ну ок, пусть нет разницы между указателями на объекты и функции. Тогда мой пример показывает что гарантии нарушаются
E>Короче говоря. Определять шаблоном статические переменные -- это общепринято. Так что если это от чего-то не разрешено в стандарте, то это баг стандарта
Про const static соглашусь. В остальных случаях баг может пролезть в результат.
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth