конструктор с переменным числом аргументов...

Тема в разделе "LANGS.C", создана пользователем cupuyc, 4 сен 2009.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    cupuyc

    Ок, начнем с самого начала. Чем не устраивает std::string + std::stringstream?
     
  2. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    cupuyc
    Открыл Америку. Переменному кол-ву параметров сто лет в обед. Не понимаю, чего тут даже обсуждать.
     
  3. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    вобщем, случилось то, ради чего я и открывал эту тему. создаю метод:

    Код (Text):
    1. void print_format(const CUtfT &str_format, ...)
    2. ...
    3. va_start(args, str_format);
    4. ...
    5. CUtfT   *s = va_arg(args, CUtfT*);
    6. ...
    7. va_end(args);
    8.  
    9. // вызов:
    10. print_format(m_str_xml_ver_lang_enc, &m_str_ver_1_0, &m_str_lang, &CUtfT<t_base_char>::get_current_encoding());
    передаю дополнительным параметром указатель на CUtfT. после выполнения CUtfT *s = va_arg(args, CUtfT*); в s какой-то бред. проанализировал содержимое стека - там не указатель, а поля структуры CUtfT, хотя я передаю именно указатель.
    поясните, пожалуйста.
     
  4. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    cupuyc

    А если так?

    print_format(m_str_xml_ver_lang_enc, (void*)&m_str_ver_1_0, (void*)&m_str_lang, (void*)&CUtfT<t_base_char>::get_current_encoding());

    Это конечно же не выход, просто интересно что выдаст твой компиллер. Кстати что за компиллер?
     
  5. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    студия девятая. кстати, попробовал сделать простенький пример - там всё пучком. при компиляции 64х кода - тоже всё норм.
     
  6. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    блин, даже с явным void* не получается. что за ёшкин кот?
     
  7. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    Код (Text):
    1. class Ca
    2. {
    3. private:
    4.     int x, y;
    5. public:
    6.     Ca(int a = 0, int b = 0)
    7.     {
    8.         x = a;
    9.         y = b;
    10.     }
    11.  
    12.     ~Ca()
    13.     {
    14.     }
    15.  
    16.     int func(int k)
    17.     {
    18.         x += k;
    19.         y -= x;
    20.  
    21.         return x + y;
    22.     }
    23.  
    24.     int get_x() const
    25.     {
    26.         return x;
    27.     }
    28.  
    29.     int get_y() const
    30.     {
    31.         return y;
    32.     }
    33.  
    34.     int format(const Ca &s, ...)
    35.     {
    36.         va_list args;
    37.  
    38.         va_start(args, s);
    39.  
    40.         Ca *p = va_arg(args, Ca*);
    41.         p->func(20);
    42.  
    43.         p = va_arg(args, Ca*);
    44.         p->func(p->get_x());
    45.  
    46.         p = va_arg(args, Ca*);
    47.         p->func(p->get_y());
    48.  
    49.         y = p->get_x();
    50.         x = p->get_y();
    51.  
    52.         va_end(args);
    53.  
    54.         return x;
    55.     }
    56. };
    57.  
    58. class Cb
    59. {
    60. private:
    61.     const Ca    m_1, m_2, m_3;
    62.     Ca  m_4;
    63.  
    64. public:
    65.     Cb() : m_1(2, 3), m_2(3, 4), m_3(0, 0), m_4(2, 2)
    66.     {
    67.     }
    68.  
    69.     ~Cb()
    70.     {
    71.     }
    72.  
    73.     void func()
    74.     {
    75.         m_4.format(m_1, &m_2, &m_3, &m_3);
    76.     }
    77. };
    78.  
    79. void Main()
    80. {
    81.     Cb  x;
    82.  
    83.     x.func();  
    84. }
    вот примерчик - на нём повторяется.
     
  8. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    cupuyc

    Видимо это очень сильное колдунство :-D
     
  9. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    подождём спеца - должно быть, тут всё слишком просто.
     
  10. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Конечно просто. Для того чтобы добраться до необходимых параметров, va_start берёт адрес передаваемого ей параметра и прибавляет его размер. В случае объекта или указателя это работает. В случае ссылки, берётся адрес не указателя в стеке, а адрес самого объекта. А объект где угодно, но ни как не в стеке. Это препятствие можно преодолеть разве что ассемблерной вставкой.
     
  11. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Имелось ввиду объект не стеке с параметрами. Операция взятия адреса ссылки, возвращает адрес ссылаемого объекта.
     
  12. maksim_

    maksim_ New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    263
    на самом деле меня интересует почему компилятор передаёт объект, а не указатель, даже если я явно указываю (void*).

    вообще говоря, можно было бы сделать и без указателей, типа Ca x = va_arg(args, Ca); но есть 2 проблемы:
    - будет вызываться конструктор копий
    - в х64 параметры передаются через указатели, даже если вызвывать m_4.format(m_1, m_2, m_3, m_3);

    у меня сложилось такое впечатление, что формат, в котором компилятор генерирует передачу параметров мало зависит от моих указаний - так как тогда вообще можно надеяться на va_xxx макросы?
     
  13. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    maksim_
    Не передаёт он объект, он передаёт ссылку. В С++ получить указатель на ссылку нельзя, можно только на сам объект. И void* нормально работает.

    Код (Text):
    1. будет вызываться конструктор копий
    Передавай через указатель.

    Нормально он генерит. Только в случае передачи ссылки, нет тривиального метода получения указателей на нужные параметры.
     
  14. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Я не совсем понимаю где же колдунство? У меня приведённый пример работает. Ссылки/указатели не мешают. Я правда не смог выяснить -- указатели ли передаются, или что: ассемблерный листинг из C++'а получается бешеный и -0s не помогает, плюс сильно "помогает" то, что я до сих пор так и не поинтересовался способами передачи аргументов на x86_64 (хотя gcc вроде пристойно передаёт, наверное это свойства g++). Но это мелочи: код ведь работает.
     
  15. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    В случае передачи ссылки, в функцию передаётся адрес объекта. В случае передачи указателем, передаётся значение этого указателя, то есть адрес который в нём хранится. Это два способа сделать одно и то же, разница между которыми существует лишь на уровне кода C++.
     
  16. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    r90
    И в случае ссылки и указателя, на уровне компилятора передаются указатели. Но чтобы получить указатель на первый необязательный параметр, нужно получить адрес и размер параметра передаваемого va_start. С++ нельзя работать со ссылками как с указателями, и операция взятия адреса у ссылки вернёт не адрес ссылки(передаваемого параметра), а адрес объекта(который хрен знает где).
     
  17. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Я не понимаю зачем работать со ссылкой как с указателем? Или ты исходишь из предположения, что stdarg.h написан без мысли о том, что его будут использовать из c++, и поэтому бездумно берёт адрес от ссылки?
    Если предположение верно, то это баг в stdarg.h. Надо писать разработчикам, жаловаться -- пускай исправляют. Если им компилятор не позволяет реализовать всё по уму, то одни должны жаловаться разработчикам компилятора, чтобы те реализовали stdarg на уровне компилятора, либо дополнили бы синтаксис C++'а своими фичами позволяющими реализовать stdarg.
    Скажем в gcc stdarg.h -- это файлик идущий в поставке с компилятором (не с glibc), и внутри него такие надписи:
    Код (Text):
    1. #define va_start(v,l)   __builtin_va_start(v,l)
    2. #define va_end(v)   __builtin_va_end(v)
    3. #define va_arg(v,l) __builtin_va_arg(v,l)
     
  18. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    r90
    Иначе чем через адрес обязательного параметра, добраться до необязательных не возможно. Получение адреса ссылки противоречит самой концепции ссылок и вводить такое в стандарт вряд ли станут. Может и можно сделать черезжопное расширение, но не факт что его поддержат другие компиляторы, а раз так, то получаем непереносимую фичу. По-этому с этим нужно просто смириться.
     
  19. maksim_

    maksim_ New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2009
    Сообщения:
    263
    ага, дошло.
    какой выход?
    юзать первым параметром указатель вместо ссылки?
    глянул в MFC - там первым параметром передаётся не CString, а PCXSTR, что, вообще говоря, глупо. если мне одновременно нужно юзать и utf и ascii строки... если это внутри шаблона...

    Код (Text):
    1. template <typename t>
    2. void func()
    3. {
    4.  CStringT<t> s;
    5.  s.format(/* х.з. */)
    6. }
     
  20. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Почему глупо передавать указатель на форматную строку? Ведь от неё не требуется какой-то изощрённой кодировки.