Неоднозначная ситуация с функцией преобразования в классе

Тема в разделе "LANGS.C", создана пользователем Ronin_, 2 июн 2017.

  1. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Моим предложением так и не воспользовались, так что всё в силе. Готов подарить 250GB-хард бедняжкам, для которых найти 10КБ места это неразрешимая проблема.
    Осталось только понять, как связаны RTTI и стек.
    Точную цитату можно из стандарта?
     
  2. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    10 Кбайт там, 10 Кбайт тут, так и набираются лишние мегабайты кода. Но беда не в том, что кода много, а в том, что он, сцуко, дублируется. В этом основная проблема.

    С исключениями в C#/Java не работали, как понимаю. То, что любое исключение содержит полный стектрейс до места, где оно было сгенерировано, не знаем. Да, может, это не совсем RTTI, но и не debug info, так как полностью выпилить стектрейс не получится.

    А вас в Гугле забанили? Эта ссылка подойдёт?
    http://www.codingstandard.com/rule/15-2-1-do-not-throw-an-exception-from-a-destructor/
     
  3. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Стектрейс нигде в типе исключения не закодирован, так что да,
    или вернее "это совсем не RTTI".
    Конечно нет, это же не цитата из стандарта. Тем более, там ни слова про UB.
     
  4. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
  5. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    RedLord,
    Какой? 15.2 Constructors and destructors [except.ctor] или 15.2 Temporary objects [class.temporary]?

    Так или иначе, ни в том, ни в другом ни слова про UB.
     
  6. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    То есть, для вас тот факт, что вызов любой функции в деструкторе может привести к std::terminate - это не UB?
     
  7. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Это ни для кого не UB.
     
  8. Ronin_

    Ronin_ Active Member

    Публикаций:
    1
    Регистрация:
    24 дек 2016
    Сообщения:
    252
    SadKo, Там сам компилятор генерирует необходимое количество перегруженных версий шаблонной функции(ака неявная специализация).
     
  9. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Это в какой реализации shared_ptr используются спинлоки?
    finally нужен убогим язычкам без RAII. В C++ явно писать try-catch нужно довольно редко, а finally и подавно не нужен. Scope guards на порядок удобнее, хотя бы потому что действия по очистке описываются сразу после выделения ресурса, а не так, как в языках с finally: захват ресурсов в начале блока, а действия по очистке где-то через -дцать строк, в конце функции, после всех блоков с catch. Смотри, не забудь удостовериться, что он освобождает всё, что надо :lol:
     
  10. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Вброс УГ в вентилятор засчитан. Теперь давайте по полочкам.

    Открываем файл /usr/include/c++/4.9/bits/shared_ptr_base.h:
    Код (C):
    1.  
    2.   template<typename _Tp, _Lock_policy _Lp>
    3.     class __shared_ptr
    4.     {
    5.       // ...
    6.       _Tp*                 _M_ptr;         // Contained pointer.
    7.       __shared_count<_Lp>  _M_refcount;    // Reference counter.
    8.     };
    9.  
    10.    // Смотрим чуть выше:
    11.      template<_Lock_policy _Lp>
    12.     class __shared_count
    13.     {
    14.       _Sp_counted_base<_Lp>*  _M_pi;
    15.     };
    16.  
    17.     // Ещё чуть выше
    18.       template<_Lock_policy _Lp = __default_lock_policy>
    19.     class _Sp_counted_base
    20.     : public _Mutex_base<_Lp>
    21.     {
    22.     private:
    23.       _Atomic_word  _M_use_count;     // #shared
    24.       _Atomic_word  _M_weak_count;    // #weak + (#shared != 0)
    25.     };
    26.  
    27.     // А теперь крутим немного ниже и смотрим multithreaded-специализацию отдельных методов:
    28.   template<>
    29.     inline bool
    30.     _Sp_counted_base<_S_single>::
    31.     _M_add_ref_lock_nothrow()
    32.     {
    33.       if (_M_use_count == 0)
    34.         return false;
    35.       ++_M_use_count;
    36.       return true;
    37.     }
    38.  
    39.   template<>
    40.     inline bool
    41.     _Sp_counted_base<_S_mutex>::
    42.     _M_add_ref_lock_nothrow()
    43.     {
    44.       __gnu_cxx::__scoped_lock sentry(*this);
    45.       if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
    46.         {
    47.           _M_use_count = 0;
    48.           return false;
    49.         }
    50.       return true;
    51.     }
    52.  
    53.   template<>
    54.     inline bool
    55.     _Sp_counted_base<_S_atomic>::
    56.     _M_add_ref_lock_nothrow()
    57.     {
    58.       // Perform lock-free add-if-not-zero operation.
    59.       _Atomic_word __count = _M_get_use_count();
    60.       do
    61.         {
    62.           if (__count == 0)
    63.             return false;
    64.           // Replace the current counter value with the old value + 1, as
    65.           // long as it's not changed meanwhile.
    66.         }
    67.       while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
    68.                                           true, __ATOMIC_ACQ_REL,
    69.                                           __ATOMIC_RELAXED));
    70.       return true;
    71.     }
    72.  
    В общем, как работает shared_ptr изнутри, не знаем, а говно в вентилятор вбрасываем. "Поздравляю тебя, Шарик, ты балбес" (C).

    Ну да, конечно, C++ - самый совершенный язык всех времён и народов, который сочетает в себе кучу парадигм, но почему-то категорически отказывается от одной из них.

    А как вы ошибки ввода-вывода обрабатываете? Или упасть по uncaught exception - это нормуль? Ну ок, ок. Про потенциальный throw std::bad_alloc из любого места, где вы используете STL, промолчим.

    Всё это замечательно, пока вы не работаете с несколькими ресурсами одновременно и не задействуете C API. То есть, не летаете в облаках темплейтнутого ООП, а спускаетесь на уровень околосистемных вызовов операционной системы. Там проще написать один раз finally, нежели начать городить тонны классов, объекты которых будут уничтожаться по деструктору (sic!).

    А что тут удостоверяться? Вот вполне себе нормальный кусок кода на Java с "нечёткой логикой" на финализации:
    Код (Java):
    1.  
    2.                 Tm_SSHMainConnection conn = getMainConnection();
    3.  
    4.                 // Create descriptor and add
    5.                 descr = new Tm_SSHConnectionDescriptor(did, getID(), getOptions());
    6.                 synchronized (m_Connections)
    7.                 {
    8.                     m_Connections.add(descr);
    9.                     descr.lock();
    10.                 }
    11.                
    12.                 try
    13.                 {
    14.                     // Open channel
    15.                     descr.open(conn);                  
    16.                    
    17.                     // Unlock descriptor only when it can work in shared mode
    18.                     if (descr.isFXP())
    19.                     {
    20.                         synchronized (m_Connections)
    21.                         {
    22.                             descr.unlock();
    23.                             m_Connections.notifyAll();
    24.                         }
    25.                     }
    26.                 }
    27.                 catch (IOException ex)
    28.                 {
    29.                     synchronized (m_Connections)
    30.                     {
    31.                         if (m_Connections.remove(descr))
    32.                         {
    33.                             m_Total--;
    34.                             m_Connections.notifyAll();
    35.                         }
    36.                     }
    37.                     throw new Tm_ConnectionException("Error while estimating remote connection", ex);
    38.                 }
    39.                 finally
    40.                 {
    41.                     if ((conn != null) && (conn.isInvalid()))
    42.                         conn.close();
    43.                 }
    44.  
     
  11. Ronin_

    Ronin_ Active Member

    Публикаций:
    1
    Регистрация:
    24 дек 2016
    Сообщения:
    252
    SadKo, да, так что вы теперь понимаете что код не дублировался?
     
  12. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Проверим путём компиляции на разных машинах и дизассемблированием?
     
  13. Ronin_

    Ronin_ Active Member

    Публикаций:
    1
    Регистрация:
    24 дек 2016
    Сообщения:
    252
    SadKo, нет, стоит почитать документацию. А ещё про перегрузку функций.

    Код (C++):
    1. #include <iostream>
    2. using namespace std;
    3.  
    4. void f(int n);
    5. void f(double d);
    6.  
    7. int main() {
    8.  
    9.     int n = 10;
    10.     double d = 16.3;
    11.  
    12.     f(n);
    13.     f(d);
    14.  
    15.     return 0;
    16. }
    17.  
    18. void f(int n) {
    19.     cout << n << endl;
    20. }
    21.  
    22. void f(double d) {
    23.     cout << d << endl;
    24. }
    И понять что компилятор за вас делает перегрузку, которая называется неявной специализацией, в случае с шаблонными функциями.
     
  14. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    То есть, вы не ставите ни во что компилятор, на котором придётся компилировать код?

    Спасибо, кэп!

    Мы говорим о разных вещах.

    Я про это:
    Код (C++):
    1.  
    2. // main.cpp
    3. #include <vector>
    4.  
    5. void put_to_vector(std::vector<void *> &v, void *ptr);
    6. void put_to_vector(std::vector<char *> &v, char *ptr);
    7.  
    8. int main()
    9. {
    10.   std::vector<void *> v1;
    11.   std::vector<char *> v2;
    12.  
    13.   char value[32] = "test";
    14.  
    15.   put_to_vector(v1, value);
    16.   put_to_vector(v2, value);
    17.  
    18.   return 0;
    19. }
    20.  
    21. // module.cpp
    22. #include <vector>
    23.  
    24. void put_to_vector(std::vector<void *> &v, void *ptr)
    25. {
    26.   v.push_back(ptr);
    27. }
    28.  
    29. void put_to_vector(std::vector<char *> &v, char *ptr)
    30. {
    31.   v.push_back(ptr);
    32. }
    33.  
    34. void put_to_vector2(std::vector<void *> &v, void *ptr)
    35. {
    36.   v.push_back(ptr);
    37. }
    38.  
    39. void put_to_vector2(std::vector<char *> &v, char *ptr)
    40. {
    41.   v.push_back(ptr);
    42. }
    43.  
    Далее:
    Код (Text):
    1.  
    2. g++ -O2 main.cpp module.cpp
    3. objdump -D a.out >a.lst
    4.  
    На выходе в a.out:
    Код (ASM):
    1.  
    2. 00000000004008b0 <_Z14put_to_vector2RSt6vectorIPvSaIS0_EES0_>:
    3.   4008b0:   48 83 ec 18     sub  $0x18,%rsp
    4.   4008b4:   48 89 74 24 08     mov  %rsi,0x8(%rsp)
    5.   4008b9:   48 8b 77 08     mov  0x8(%rdi),%rsi
    6.   4008bd:   48 3b 77 10     cmp  0x10(%rdi),%rsi
    7.   4008c1:   74 2d     je  4008f0 <_Z14put_to_vector2RSt6vectorIPvSaIS0_EES0_+0x40>
    8.   4008c3:   48 85 f6     test  %rsi,%rsi
    9.   4008c6:   74 20     je  4008e8 <_Z14put_to_vector2RSt6vectorIPvSaIS0_EES0_+0x38>
    10.   4008c8:   48 8b 44 24 08     mov  0x8(%rsp),%rax
    11.   4008cd:   48 89 06     mov  %rax,(%rsi)
    12.   4008d0:   48 8b 47 08     mov  0x8(%rdi),%rax
    13.   4008d4:   48 83 c0 08     add  $0x8,%rax
    14.   4008d8:   48 89 47 08     mov  %rax,0x8(%rdi)
    15.   4008dc:   48 83 c4 18     add  $0x18,%rsp
    16.   4008e0:   c3     retq  
    17.   4008e1:   0f 1f 80 00 00 00 00    nopl  0x0(%rax)
    18.   4008e8:   31 c0     xor  %eax,%eax
    19.   4008ea:   eb e8     jmp  4008d4 <_Z14put_to_vector2RSt6vectorIPvSaIS0_EES0_+0x24>
    20.   4008ec:   0f 1f 40 00     nopl  0x0(%rax)
    21.   4008f0:   48 8d 54 24 08     lea  0x8(%rsp),%rdx
    22.   4008f5:   e8 f6 00 00 00     callq  4009f0 <_ZNSt6vectorIPvSaIS0_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS0_S2_EERKS0_>
    23.   4008fa:   eb e0     jmp  4008dc <_Z14put_to_vector2RSt6vectorIPvSaIS0_EES0_+0x2c>
    24.   4008fc:   0f 1f 40 00     nopl  0x0(%rax)
    25.  
    26. 0000000000400900 <_Z13put_to_vectorRSt6vectorIPvSaIS0_EES0_>:
    27.   400900:   48 83 ec 18     sub  $0x18,%rsp
    28.   400904:   48 89 74 24 08     mov  %rsi,0x8(%rsp)
    29.   400909:   48 8b 77 08     mov  0x8(%rdi),%rsi
    30.   40090d:   48 3b 77 10     cmp  0x10(%rdi),%rsi
    31.   400911:   74 2d     je  400940 <_Z13put_to_vectorRSt6vectorIPvSaIS0_EES0_+0x40>
    32.   400913:   48 85 f6     test  %rsi,%rsi
    33.   400916:   74 20     je  400938 <_Z13put_to_vectorRSt6vectorIPvSaIS0_EES0_+0x38>
    34.   400918:   48 8b 44 24 08     mov  0x8(%rsp),%rax
    35.   40091d:   48 89 06     mov  %rax,(%rsi)
    36.   400920:   48 8b 47 08     mov  0x8(%rdi),%rax
    37.   400924:   48 83 c0 08     add  $0x8,%rax
    38.   400928:   48 89 47 08     mov  %rax,0x8(%rdi)
    39.   40092c:   48 83 c4 18     add  $0x18,%rsp
    40.   400930:   c3     retq  
    41.   400931:   0f 1f 80 00 00 00 00    nopl  0x0(%rax)
    42.   400938:   31 c0     xor  %eax,%eax
    43.   40093a:   eb e8     jmp  400924 <_Z13put_to_vectorRSt6vectorIPvSaIS0_EES0_+0x24>
    44.   40093c:   0f 1f 40 00     nopl  0x0(%rax)
    45.   400940:   48 8d 54 24 08     lea  0x8(%rsp),%rdx
    46.   400945:   e8 a6 00 00 00     callq  4009f0 <_ZNSt6vectorIPvSaIS0_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS0_S2_EERKS0_>
    47.   40094a:   eb e0     jmp  40092c <_Z13put_to_vectorRSt6vectorIPvSaIS0_EES0_+0x2c>
    48.   40094c:   0f 1f 40 00     nopl  0x0(%rax)
    49.  
    50. 0000000000400950 <_Z13put_to_vectorRSt6vectorIPcSaIS0_EES0_>:
    51.   400950:   48 83 ec 18     sub  $0x18,%rsp
    52.   400954:   48 89 74 24 08     mov  %rsi,0x8(%rsp)
    53.   400959:   48 8b 77 08     mov  0x8(%rdi),%rsi
    54.   40095d:   48 3b 77 10     cmp  0x10(%rdi),%rsi
    55.   400961:   74 2d     je  400990 <_Z13put_to_vectorRSt6vectorIPcSaIS0_EES0_+0x40>
    56.   400963:   48 85 f6     test  %rsi,%rsi
    57.   400966:   74 20     je  400988 <_Z13put_to_vectorRSt6vectorIPcSaIS0_EES0_+0x38>
    58.   400968:   48 8b 44 24 08     mov  0x8(%rsp),%rax
    59.   40096d:   48 89 06     mov  %rax,(%rsi)
    60.   400970:   48 8b 47 08     mov  0x8(%rdi),%rax
    61.   400974:   48 83 c0 08     add  $0x8,%rax
    62.   400978:   48 89 47 08     mov  %rax,0x8(%rdi)
    63.   40097c:   48 83 c4 18     add  $0x18,%rsp
    64.   400980:   c3     retq  
    65.   400981:   0f 1f 80 00 00 00 00    nopl  0x0(%rax)
    66.   400988:   31 c0     xor  %eax,%eax
    67.   40098a:   eb e8     jmp  400974 <_Z13put_to_vectorRSt6vectorIPcSaIS0_EES0_+0x24>
    68.   40098c:   0f 1f 40 00     nopl  0x0(%rax)
    69.   400990:   48 8d 54 24 08     lea  0x8(%rsp),%rdx
    70.   400995:   e8 f6 01 00 00     callq  400b90 <_ZNSt6vectorIPcSaIS0_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS0_S2_EERKS0_>
    71.   40099a:   eb e0     jmp  40097c <_Z13put_to_vectorRSt6vectorIPcSaIS0_EES0_+0x2c>
    72.   40099c:   0f 1f 40 00     nopl  0x0(%rax)
    73.  
    74. 00000000004009a0 <_Z14put_to_vector2RSt6vectorIPcSaIS0_EES0_>:
    75.   4009a0:   48 83 ec 18     sub  $0x18,%rsp
    76.   4009a4:   48 89 74 24 08     mov  %rsi,0x8(%rsp)
    77.   4009a9:   48 8b 77 08     mov  0x8(%rdi),%rsi
    78.   4009ad:   48 3b 77 10     cmp  0x10(%rdi),%rsi
    79.   4009b1:   74 2d     je  4009e0 <_Z14put_to_vector2RSt6vectorIPcSaIS0_EES0_+0x40>
    80.   4009b3:   48 85 f6     test  %rsi,%rsi
    81.   4009b6:   74 20     je  4009d8 <_Z14put_to_vector2RSt6vectorIPcSaIS0_EES0_+0x38>
    82.   4009b8:   48 8b 44 24 08     mov  0x8(%rsp),%rax
    83.   4009bd:   48 89 06     mov  %rax,(%rsi)
    84.   4009c0:   48 8b 47 08     mov  0x8(%rdi),%rax
    85.   4009c4:   48 83 c0 08     add  $0x8,%rax
    86.   4009c8:   48 89 47 08     mov  %rax,0x8(%rdi)
    87.   4009cc:   48 83 c4 18     add  $0x18,%rsp
    88.   4009d0:   c3     retq  
    89.   4009d1:   0f 1f 80 00 00 00 00    nopl  0x0(%rax)
    90.   4009d8:   31 c0     xor  %eax,%eax
    91.   4009da:   eb e8     jmp  4009c4 <_Z14put_to_vector2RSt6vectorIPcSaIS0_EES0_+0x24>
    92.   4009dc:   0f 1f 40 00     nopl  0x0(%rax)
    93.   4009e0:   48 8d 54 24 08     lea  0x8(%rsp),%rdx
    94.   4009e5:   e8 a6 01 00 00     callq  400b90 <_ZNSt6vectorIPcSaIS0_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS0_S2_EERKS0_>
    95.   4009ea:   eb e0     jmp  4009cc <_Z14put_to_vector2RSt6vectorIPcSaIS0_EES0_+0x2c>
    96.   4009ec:   0f 1f 40 00     nopl  0x0(%rax)
    97.  
    Четыре (!) абсолютно одинаковые функции. Согласно вашей фразе:
    Функция должна получиться одна.
     
  15. Ronin_

    Ronin_ Active Member

    Публикаций:
    1
    Регистрация:
    24 дек 2016
    Сообщения:
    252
    Это что сейчас мну прочитал?

    Как она одна получится, если компилятор автоматически основываясь на ваших типах данных генерирует необходимое количество шаблонных функций?

    Если хотите явную специализацию, создайте её руками, но тогда теряется смысл шаблона.
     
  16. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Вот и получается, что я про Фому, а вы про Ерёму, и, к тому же, не к месту.
    Я говорил не про специализацию функций, а про то, что компилятор каждый раз будет генерить новый код, будь то char *, int * или void *, пусть даже изнутри эти указатели будут обрабатываться абсолютно идентично.
    А ваш вброс про специализации вообще не к месту.

    Эта цитата была про то, что, фактически, я и подтвердил: 4 одинаковые вплоть до инструкции функции, которые занимают место в исполняемом файле.
     
  17. Ronin_

    Ronin_ Active Member

    Публикаций:
    1
    Регистрация:
    24 дек 2016
    Сообщения:
    252
    SadKo, не горячитесь, вы видимо не донца понимаете что такое - специализация, в этом ничего страшного нет.

    Код (C++):
    1. #include <iostream>
    2. #include <locale>
    3. #include <typeinfo>
    4. using namespace std;
    5.  
    6. template<class T> void f(T a)
    7. {
    8.     cout << "Здесь неявная специализация для типа: " << typeid(a).name() << endl;
    9. }
    10.  
    11. template<> void f<double>(double d)
    12. {
    13.     cout << "Здесь явная специализация для типа double" << endl;
    14. }
    15.  
    16. int main()
    17. {
    18.     setlocale(LC_ALL, "Rus");
    19.     int n = 8;
    20.     double d = 16;
    21.     char ch = 'R';
    22.    
    23.     f(n);
    24.     f(d);
    25.     f(ch);
    26.    
    27.     return 0;
    28. }
    [​IMG]
     

    Вложения:

  18. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Ты сделал вид, что мой вопрос не относится к твоему утверждению и просто нашёл, что где-то в хедерах, относящихся к shared_ptr, есть локи.
    Твоим утверждением было "при попытке изменить shared_ptr в multithreaded-среде вы постоянно будете дёргать спин-блокировки". Покажи, что эти локи захватываются "при попытке изменить shared_ptr" (что вообще относится к изменению shared_ptr? копирование/уничтожение/присваивание другому shared_ptr?).

    Ты правда так считаешь? Бгг.

    Они разные бывают, эти ошибки.

    Да нет, давайте поговорим. Это, как раз таки, интересно.

    Такие ресурсы обычно оборачивают в классы. Если наступает случай, когда "обычно" не подходит, можно задействовать scope guard.

    Т.е. это довольно специальный случай. В каких-то специальных случаях finally может быть проще, никто не спорит, что они таки случаи существуют.
    А вот превращать утверждение "в специальных случаях finally может быть проще" в "finally проще" это пример демагогии.

    Ну раз задействование C API и дёргание сисколов — это типичное применение Java, то теперь понятно, зачем там finally.

    Действительно, ведь ты специально подобрал код, в котором ресурс один.
    "Всё это замечательно, пока вы не работаете с несколькими ресурсами одновременно". А если посмотреть на код, в котором несколько ресурсов одновременно, то там получается либо простыня из проверок на null, либо лапша из вложенных блоков try-catch-finally.

    Да-да! Я бы даже сказал "типичный кусок кода для Java". Эти проверки на null...
    Проблема try-catch-finally в том, что блоки кода, которые выполняются всегда (try и finally) разрываются блоками, которые нужны только в исключительных случаях. Т.е. редко.
    Такое свойство try-catch-finally сближает со стилем обработки ошибок в C.
     
  19. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Нет, это разные функции.
    Для каждой специализации шаблона получается одна функция.
     
    Ronin_ нравится это.
  20. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Нет, это вы считаете, что я идиот и не знаю, что такое специализация шаблона. Достаточно вспомнить, что такое std::vector<bool>, чтобы понять это.