Static variables & templates
От: Аноним  
Дата: 20.10.09 20:24
Оценка:
Занятная штука:
template<typename T>
class counter{
    static T cnt;
public:
    counter(){
        cnt++;
    }

    ~counter(){
        cnt--;
    }
};

template<typename T>
int counter<T>::cnt = 0;

В функции main:
counter<int> i;
counter<int> j;

counter<float> f; //Понятно, ошибка C2371: 'cnt' : redefinition; different basic types


Так как быть с шаблонными классами и статическими элементами??
добавлена разметка — Кодт
Re: Static variables & templates
От: Andrew S Россия http://alchemy-lab.com
Дата: 20.10.09 21:26
Оценка: +1
А>template<typename T>
А>int counter<T>::cnt = 0;

А>В функции main:

А>counter<int> i;
А>counter<int> j;

А>counter<float> f; //Понятно, ошибка C2371: 'cnt' : redefinition; different basic types



А>Так как быть с шаблонными классами и статическими элементами??


T counter<T>::cnt = T();
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: Static variables & templates
От: zaufi Земля  
Дата: 20.10.09 21:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Занятная штука:


А>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... в таком случае все работает...
Re[2]: Static variables & templates
От: zaufi Земля  
Дата: 20.10.09 21:32
Оценка:
Здравствуйте, 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 все также буит работать...
Re[2]: Static variables & templates
От: Caracrist https://1pwd.org/
Дата: 20.10.09 21:43
Оценка: +1
Здравствуйте, Andrew S, Вы писали:

А>>template<typename T>

А>>int counter<T>::cnt = 0;

А>>В функции main:

А>>counter<int> i;
А>>counter<int> j;

А>>counter<float> f; //Понятно, ошибка C2371: 'cnt' : redefinition; different basic types



А>>Так как быть с шаблонными классами и статическими элементами??


AS>T counter<T>::cnt = T();

скорее
static int cnt;
~~~~~
~lol~~
~~~ Single Password Solution
Re: Static variables & templates
От: ffk  
Дата: 21.10.09 03:45
Оценка: -3
Здравствуйте, Аноним, Вы писали:

А>Занятная штука:


А>template<typename T>

А>class counter{
А> //static T cnt;
А>public:
А> counter(){
А> cnt()++;
А> }

А> ~counter(){

А> cnt()--;
А> }
A>private:
A> int& cnt() {static int cnt_ = 0; return cnt;}
А>};
Re[2]: Static variables & templates
От: Caracrist https://1pwd.org/
Дата: 21.10.09 06:45
Оценка:
Здравствуйте, 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>
А>};

это плохо без особой нужды использовать статические в функции. Это всё равно что добавить if (true) который никогда не вырежит компилятор. И должно быть оправдание для такого действия.
~~~~~
~lol~~
~~~ Single Password Solution
Re[3]: Static variables & templates
От: ffk  
Дата: 21.10.09 07:36
Оценка:
Здравствуйте, 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% это пофиг, даже не заметешь.
Критикуешь, предложи более красивое решение.
Re[4]: Static variables & templates
От: Caracrist https://1pwd.org/
Дата: 21.10.09 07:53
Оценка: +1
Здравствуйте, ffk, Вы писали:

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


ffk>В 99.99% это пофиг, даже не заметешь.

ffk>Критикуешь, предложи более красивое решение.

уже предложил:
http://www.rsdn.ru/forum/cpp/3576649.1.aspx
Автор: Caracrist
Дата: 21.10.09


в целом оно выглядит вот так:
template<typename T>
class counter{
static int cnt;
public:
counter(){
cnt++;
}

~counter(){
cnt--;
}
// тут гдето должны быть публичные функции или friends иначе этот счётчик никогда никто не прочтёт
};

template<typename T>
int counter<T>::cnt = 0;


простота залог успеха
~~~~~
~lol~~
~~~ Single Password Solution
Re: Static variables & templates
От: dcb-BanDos Россия  
Дата: 21.10.09 08:46
Оценка:
Здравствуйте, Аноним, Вы писали:


А>Так как быть с шаблонными классами и статическими элементами??


что-то я не понял, есть желание использовать для счетчика вместо int скажем std::complex?
если нет, то и используй int в шаблоне(static int count
Ничто не ограничивает полет мысли программиста так, как компилятор.
Re[5]: Static variables & templates
От: ffk  
Дата: 21.10.09 09:30
Оценка:
Здравствуйте, Caracrist, Вы писали:

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


C>template<typename T>

C>int counter<T>::cnt = 0;
C>[/ccode]

C>простота залог успеха


Мда,.. не знал что темплейтные статические мемберы можно прямо в хидере инстнционировать.
Re[3]: Static variables & templates
От: Andrew S Россия http://alchemy-lab.com
Дата: 21.10.09 18:17
Оценка:
А>>>template<typename T>
А>>>int counter<T>::cnt = 0;

А>>>В функции main:

А>>>counter<int> i;
А>>>counter<int> j;

А>>>counter<float> f; //Понятно, ошибка C2371: 'cnt' : redefinition; different basic types



А>>>Так как быть с шаблонными классами и статическими элементами??


AS>>T counter<T>::cnt = T();

C>скорее
C>static int cnt;

смотря какую семантику имеет counter. Из исходного сообщения она не очевидна.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: Static variables & templates
От: gear nuke  
Дата: 21.10.09 20:00
Оценка: :)
Здравствуйте, 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
Re[6]: Static variables & templates
От: Andrew S Россия http://alchemy-lab.com
Дата: 21.10.09 20:32
Оценка: +1
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>>простота залог успеха


GN>Насколько успешно такой хидер может быть включён в несколько единиц трансляции? Без использования __declspec(selectany)


А что, есть сомнения?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[7]: Static variables & templates
От: gear nuke  
Дата: 21.10.09 21:51
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>А что, есть сомнения?


Да, есть. Не могу найти, где это разрешено в Стандарте.

Изменю немного пример

// t.hpp
template<typename T>
struct counter{
  static int cnt;
};

// t.cpp
#include "t.hpp"

template<typename T>
int counter<T>::cnt = -1;

void* f();
int main()
{
  counter <int> c;
  void* volatile p = &c.cnt;
  p = f();
}

// t2.cpp
#include "t.hpp"

template<typename T>
int counter<T>::cnt = 1;

void* f()
{
  counter <int> c;
  void* volatile p = &c.cnt;
  return p;
}

Собираем так:
cl /FAs t.cpp t2.cpp

PUBLIC    ?cnt@?$counter@H@@2HA                ; counter<int>::cnt
PUBLIC    _main
EXTRN    ?f@@YAPAXXZ:PROC                ; f
;    COMDAT ?cnt@?$counter@H@@2HA
; File t.cpp
_DATA    SEGMENT
?cnt@?$counter@H@@2HA DD 0ffffffffH            ; counter<int>::cnt
; Function compile flags: /Odtp
_DATA    ENDS
_TEXT    SEGMENT
_p$ = -4                        ; size = 4
_main    PROC

; 8    : {

    push    ebp
    mov    ebp, esp
    sub    esp, 8

; 9    :   counter <int> c;
; 10   :   void* volatile p = &c.cnt;

    mov    DWORD PTR _p$[ebp], OFFSET ?cnt@?$counter@H@@2HA ; counter<int>::cnt

; 11   :   p = f();

    call    ?f@@YAPAXXZ                ; f
    mov    DWORD PTR _p$[ebp], eax

; 12   : }

    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0
_main    ENDP
_TEXT    ENDS
END

PUBLIC    ?cnt@?$counter@H@@2HA                ; counter<int>::cnt
PUBLIC    ?f@@YAPAXXZ                    ; f
;    COMDAT ?cnt@?$counter@H@@2HA
; File t2.cpp
_DATA    SEGMENT
?cnt@?$counter@H@@2HA DD 01H                ; counter<int>::cnt
; Function compile flags: /Odtp
_DATA    ENDS
_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
_TEXT    ENDS
END

Намеренно опущу изучение слинкованного бинарника.

2й вариант сборки:
cl /GL /FAs t.cpp t2.cpp

PUBLIC    ?cnt@?$counter@H@@2HA                ; counter<int>::cnt
EXTRN    @__security_check_cookie@4:PROC
;    COMDAT ?cnt@?$counter@H@@2HA
_DATA    SEGMENT
?cnt@?$counter@H@@2HA DD 0ffffffffH            ; counter<int>::cnt
PUBLIC    _main
; Function compile flags: /Odtp
; File t.cpp
_TEXT    SEGMENT
_p$ = -4                        ; size = 4
_main    PROC

; 8    : {

    push    ebp
    mov    ebp, esp
    sub    esp, 8

; 9    :   counter <int> c;
; 10   :   void* volatile p = &c.cnt;

    mov    DWORD PTR _p$[ebp], OFFSET ?cnt@?$counter@H@@2HA ; counter<int>::cnt

; 11   :   p = f();

    call    ?f@@YAPAXXZ                ; f
    mov    DWORD PTR _p$[ebp], eax

; 12   : }

    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0
_main    ENDP
_TEXT    ENDS
END

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]: Чем статические данные отличаются от методов?
От: Erop Россия  
Дата: 22.10.09 09:19
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Здравствуйте, Andrew S, Вы писали:


AS>>А что, есть сомнения?


GN>Да, есть. Не могу найти, где это разрешено в Стандарте.


В принципе, есть похожие объекты -- это шаблоны функций и методов. Где, например, написано про них?

GN>
// t.hpp
GN>template<typename T>
GN>int counter<T>::cnt = -1;
GN>template<typename T>
GN>int counter<T>::cnt = 1;
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]: Чем статические данные отличаются от методов?
От: gear nuke  
Дата: 22.10.09 11:03
Оценка:
Здравствуйте, Erop, Вы писали:

E>В принципе, есть похожие объекты -- это шаблоны функций и методов. Где, например, написано про них?


Можно иметь 2 копии одной функции и вызывать их из разных мест — наблюдаемое поведение не изменится. Если имеется 2 копии одного объекта, то это подразумевает возможность хранения разных состояний, что и демонстрирует мой пример.

GN>>
// t.hpp
GN>>template<typename T>
GN>>int counter<T>::cnt = -1;
GN>>template<typename T>
GN>>int counter<T>::cnt = 1;
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]: Чем статические данные отличаются от методов?
От: Erop Россия  
Дата: 22.10.09 11:30
Оценка: +1
Здравствуйте, 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]: Чем статические данные отличаются от методов?
От: Caracrist https://1pwd.org/
Дата: 22.10.09 11:31
Оценка: +1
Здравствуйте, gear nuke, Вы писали:

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


E>>В принципе, есть похожие объекты -- это шаблоны функций и методов. Где, например, написано про них?


GN>Можно иметь 2 копии одной функции и вызывать их из разных мест — наблюдаемое поведение не изменится.


template<typename T>

struct S
{
void myFunc()
{
static int oproverzhenie;
// blablabla
}
};
~~~~~
~lol~~
~~~ Single Password Solution
Re[11]: Чем статические данные отличаются от методов?
От: gear nuke  
Дата: 22.10.09 14:34
Оценка:
Здравствуйте, 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
Re[11]: Чем статические данные отличаются от методов?
От: gear nuke  
Дата: 22.10.09 14:34
Оценка:
Здравствуйте, Caracrist, Вы писали:

C>template<typename T>


C>
C>struct S
C>{
C>void myFunc()
C>{
C>static int oproverzhenie;
C>// blablabla
C>}
C>};
C>


Отлично. Чем же этот вариант отличается от Re: Static variables &amp; templates
Автор: ffk
Дата: 21.10.09
?
.
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[11]: Чем статические данные отличаются от методов?
От: gear nuke  
Дата: 22.10.09 17:12
Оценка:
Здравствуйте, Erop, Вы писали:

E>в исходном переменная имеет одно определение...


Может быть вот такое "одно" определение в хидере:
template<typename T>
int counter<T>::cnt = __COUNTER__;
.
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[12]: Чем статические данные отличаются от методов?
От: Caracrist https://1pwd.org/
Дата: 22.10.09 17:49
Оценка:
Здравствуйте, gear nuke, Вы писали:

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


C>>template<typename T>


C>>
C>>struct S
C>>{
C>>void myFunc()
C>>{
C>>static int oproverzhenie;
C>>// blablabla
C>>}
C>>};
C>>


GN>Отлично. Чем же этот вариант отличается от Re: Static variables &amp; templates
Автор: ffk
Дата: 21.10.09
?


тем, что сдесь оно без контекста и демонстрирует принципиальную возможность того, что "наблюдаемое поведение да изменится"
А то что ни в каких случаях, ни за что не оправдано использование статиков в функциях, я не говорил.
~~~~~
~lol~~
~~~ Single Password Solution
Re[12]: Чем статические данные отличаются от методов?
От: Erop Россия  
Дата: 22.10.09 19:34
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Может быть вот такое "одно" определение в хидере:

GN>
GN>template<typename T>
GN>int counter<T>::cnt = __COUNTER__;
GN>


Во-первых, __COUNTER__ в разных TU считает независимо.
Во-вторых, или и заботай ODR, что ли. Для всяких объектов с ослабленным ODR, вроде inline-функций и т. п. требуют, чтобы определения присутствующие во всех TU были эквивалентны...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[12]: Чем статические данные отличаются от методов?
От: Erop Россия  
Дата: 22.10.09 19:44
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>В случае с функциями транслятор может сравнить например их AST и убрать лишнюю копию.

Что мешает сравнить определения статического члена?
Кроме того, обычно лишнюю копию выбрасывает линкер, а не компилятор...

GN>А зачем они тогда приводились как пример?

Затем, что всегда можно написать так например:
// 0.h
template<typename T> T foo( T t ) { return t; }
typedef int int2int( int );
extern int2int* getFooPtr();

//1.cpp
#include "0.h"
extern int2int* getFooPtr()
{
    return foo<int>;
}

//2.cpp
#include "0.h"
void bar()
{
    assert( getFooPtr() == &foo<int> );
}


GN>Она имеет 2 одинаковых определения в разных TU.

Изучи как так получается, что inline-функции не противоречат ODR...

GN>Слинкуется. Я проверял, ассемблерные листинги не меняются.

Пример приведи, что именно исправлял? Было два cpp с кодом
template<> int xxx<int>::counter = 10;
и
template<> int xxx<int>::counter = 20;


GN>А тут имеет место быть ослабление ODR за счёт inline.

ОТкуда inline в коде
template<typename T> T foo( T t ) { return t; }

Но ты кое в чём прав. Ослабление ODR таки имеет место. Но оно бывает не только для inline, но и для разных других данных и кода. Например для таблицы виртуальных функций класса или для результатов неявной инстанциации шаблонов...

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


Ничего не нарушается. В твоём примере нарушено ODR! Даже ослабленное. Это снимает ответственность за последствия с авторов транслятора!

GN>Про const static соглашусь. В остальных случаях баг может пролезть в результат.

Нет. Не const тоже. Вообще-то если статическое поле имеет нетривиальные конструктор или деструктор, то пофиг const оно или не сonst...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[13]: Чем статические данные отличаются от методов?
От: gear nuke  
Дата: 23.10.09 10:57
Оценка:
Здравствуйте, Erop, Вы писали:

E>Что мешает сравнить определения статического члена?


Я не знаю, по моему мой пример вообще линковаться не должен

E>Кроме того, обычно лишнюю копию выбрасывает линкер, а не компилятор...


Да, причём не сравнивая

GN>>А зачем они тогда приводились как пример?

E>Затем, что всегда можно написать так например:

Раз так можно, то чем принципиально Re: Static variables &amp; templates
Автор: ffk
Дата: 21.10.09
хуже? Оно будет работать и для не-шаблонов.

GN>>Она имеет 2 одинаковых определения в разных TU.

E>Изучи как так получается, что inline-функции не противоречат ODR...

Получается как в стандарте:

3.2/3 Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is used.


GN>>Слинкуется. Я проверял, ассемблерные листинги не меняются.

E>Пример приведи, что именно исправлял? Было два cpp с кодом
template<> int xxx<int>::counter = 10;
и
template<> int xxx<int>::counter = 20;


Да, так и было, только значения другие.

E>Ничего не нарушается. В твоём примере нарушено ODR! Даже ослабленное. Это снимает ответственность за последствия с авторов транслятора!


Да, так получилось, я его явно нарушил. Вот если бы еще все остальные случаи были б такими же явными. И с __COUNTER__ можно намудрить, как раз из-за независимости подсчёта в разных TU.

GN>>Про const static соглашусь. В остальных случаях баг может пролезть в результат.

E>Нет. Не const тоже. Вообще-то если статическое поле имеет нетривиальные конструктор или деструктор, то пофиг const оно или не сonst...

Опс мне следовало написать "static const интегральные типы и enum" Это при том что я вообще всё люблю писать в заголовках и не люблю много TU. Но вот под определение такого статика отдельной TU не жалко, если надо. До сих пор думаю что это такая багофича MSVC.
.
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[14]: Чем статические данные отличаются от методов?
От: Erop Россия  
Дата: 23.10.09 14:28
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Опс мне следовало написать "static const интегральные типы и enum" Это при том что я вообще всё люблю писать в заголовках и не люблю много TU. Но вот под определение такого статика отдельной TU не жалко, если надо. До сих пор думаю что это такая багофича MSVC.


Вроде бы везде можно определять шаблоны статических членов...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Static variables & templates
От: Aleх  
Дата: 24.10.09 16:11
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Занятная штука:

А>
А>template<typename T>
А>class counter{
А>    static T cnt;
А>public:
А>    counter(){
А>        cnt++;
А>    }

А>    ~counter(){
А>        cnt--;
А>    }
А>};

А>template<typename T>
А>int counter<T>::cnt = 0;

А>В функции main:
А>counter<int> i;
А>counter<int> j;

А>counter<float> f; //Понятно, ошибка C2371: 'cnt' : redefinition; different basic types
А>


А>Так как быть с шаблонными классами и статическими элементами??


template<typename T> class counter
{
    static T cnt;
public:
    counter() { cnt++; }
    ~counter() { cnt--; }
};

template<typename T> T counter<T>::cnt = T();

Может быть так?
Всё зависит от того что нужно автору, если ему нужно считать количество созданных классов определенного типа (class A : counter<A>), то стоит воспользоваться int, как отписали выше.
Re[8]: Static variables & templates
От: Николай Ивченков  
Дата: 25.10.09 16:21
Оценка:
gear nuke:

GN>Здравствуйте, Andrew S, Вы писали:


AS>>А что, есть сомнения?


GN>Да, есть. Не могу найти, где это разрешено в Стандарте.


3.2/5: "There can be more than one definition of a class type (clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (clause 14), non-static function template (14.5.5), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.4) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements [...]" — дальше идёт описание требований к идентичности определений.

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.).

Это объявление, не являющееся определением (см. 14.7.3/15).
Re[9]: Static variables & templates
От: gear nuke  
Дата: 26.10.09 11:01
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ> — дальше идёт описание требований к идентичности определений.


Вот это важная деталь. Другими словами Стандарт разрешает, но на свой страх и риск.

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.).

НИ>Это объявление, не являющееся определением (см. 14.7.3/15).


Это моя ошибка, следовало не вырывать из контекста и писать так

// 1.cpp
template<> int counter<int>::cnt = 1;

// 2.cpp
template<> int counter<int>::cnt = -1;

что я и пробовал (успешно) собрать.




Мой поинт в том, что Re: Static variables &amp; templates
Автор: ffk
Дата: 21.10.09
и предложенная замена — суть одни и те же подводные камни.
.
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[15]: Чем статические данные отличаются от методов?
От: gear nuke  
Дата: 26.10.09 11:13
Оценка:
Здравствуйте, Erop, Вы писали:

E>Вроде бы везде можно определять шаблоны статических членов...


May и can по-нашему оба значат "можно". Про что в Стандарте написано "may", в проектные требования может пойти как "can, but... shall not"
.
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]: Static variables & templates
От: Николай Ивченков  
Дата: 26.10.09 14:02
Оценка:
gear nuke:

GN>Другими словами Стандарт разрешает, но на свой страх и риск.


Я не понял твою мысль. Что именно он, по-твоему, разрешает?

GN>
// 1.cpp
GN>template<> int counter<int>::cnt = 1;

GN>// 2.cpp
GN>template<> int counter<int>::cnt = -1;
GN>

GN>что я и пробовал (успешно) собрать.

Здесь имеет место undefined behavior. Реализация не обязана диагностировать данное нарушение ODR.

GN>Мой поинт в том, что Re: Static variables &amp; templates
Автор: ffk
Дата: 21.10.09
и предложенная замена — суть одни и те же подводные камни.


Я снова не понял твою мысль. Что не так в примере по этой ссылке и что за "предложенная замена" имеется в виду?
Re[11]: Static variables & templates
От: gear nuke  
Дата: 26.10.09 16:58
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ>Я не понял твою мысль. Что именно он, по-твоему, разрешает?


Несколько определений статического члена шаблона класса.

GN>>
// 1.cpp
GN>>template<> int counter<int>::cnt = 1;

GN>>// 2.cpp
GN>>template<> int counter<int>::cnt = -1;
GN>>

GN>>что я и пробовал (успешно) собрать.

НИ>Здесь имеет место undefined behavior. Реализация не обязана диагностировать данное нарушение ODR.


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

GN>>Мой поинт в том, что Re: Static variables &amp; templates
Автор: ffk
Дата: 21.10.09
и предложенная замена — суть одни и те же подводные камни.


НИ>Я снова не понял твою мысль. Что не так в примере по этой ссылке


Этот вопрос меня тоже интересует, о чем я и спрашивал поставивших минусу

НИ> и что за "предложенная замена" имеется в виду?


Предложено было заменить функцию-член данными.
.
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
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.