С++ union initialization
От: c-smile Канада http://terrainformatica.com
Дата: 21.03.20 04:57
Оценка:
Есть такая декларация:

struct func {
  const char* name;
  int argc;
  union {
    int(*f0)(void*);
    int(*f1)(void*, int);
  } f;
};


Есть такая функция

int foo(void* p, int v) { return 42; };


Нужно написать инициализатор типа этого:

func fdef = { "meth1", 1, {.f1 = foo} };


Но чего-то не выходит каменный цветок, во всяком случае в VS2017

Ругается на '.' тут:

func fdef = { "meth1", 1, {.f1 = foo} };
---------------------------^


Можно как-то победить это безобразие?
Отредактировано 21.03.2020 4:59 c-smile . Предыдущая версия .
Re: С++ union initialization
От: Alexander G Украина  
Дата: 21.03.20 05:25
Оценка: 42 (1)
Здравствуйте, c-smile, Вы писали:

CS>Ругается на '.' тут:


CS>
CS>func fdef = { "meth1", 1, {.f1 = foo} };
CS>---------------------------^
CS>


CS>Можно как-то победить это безобразие?


В C++ designated initializers вошли с C++20.

Как расширение в MSVC их не было тоже.
Русский военный корабль идёт ко дну!
Re: С++ union initialization
От: Reset  
Дата: 21.03.20 05:28
Оценка:
Во-первых, открой для себя божественный болт. Там правда нет 2017, зато он позволяет переключаться между компиляторами и ты сможешь открыть для себя, во-вторых, /std:c++latest (в сообщении об ошибке компиляции при выборе последнего MSVC). Ну и, в-третьих, он позволяет шарить код, давая ссылку на него.
Re: С++ union initialization
От: Alexander G Украина  
Дата: 21.03.20 05:34
Оценка: 42 (1)
Здравствуйте, c-smile, Вы писали:


CS>Но чего-то не выходит каменный цветок, во всяком случае в VS2017


CS>Можно как-то победить это безобразие?


Накидай constexpr конструкторов, будет такая же статическая инициализация.
Если перергузки конструктора по типу активного мембера выглядят ненадёжными или непонятными, добавить тип-тег

Примерно так
struct func {
  const char* name;
  int argc;
  
  static struct tag_f0_t {} tag_f0;
  static struct tag_f1_t {} tag_f1;
  
  union U {
    int(*f0)(void*);
    int(*f1)(void*, int);

    constexpr U(decltype(f0) f0, tag_f0) : f0(f0) {}
    constexpr U(decltype(f1) f1, tag_f1) : f1(f1) {}
  } f;
};


func fdef = { "meth1", 1, { foo, tag_f0 } };
Русский военный корабль идёт ко дну!
Re: С++ union initialization
От: rg45 СССР  
Дата: 21.03.20 05:51
Оценка: 63 (1)
Здравствуйте, c-smile, Вы писали:

CS>Но чего-то не выходит каменный цветок, во всяком случае в VS2017

CS>Ругается на '.' тут:
CS>Можно как-то победить это безобразие?

Ну, ругается потому, что Designated initializers появляются только с C++20.

Чтобы победить, я бы сделал вложенный union полностю анонимным (убрал бы имя члена f) и снабдил бы класс func набором необходимых конструкторов:

http://coliru.stacked-crooked.com/a/76e0848b39685871

struct func {

    using F0 = int(void*);
    using F1 = int(void*, int);

    const char* name {};
    int argc {};
    union {
        F0* f0 {};
        F1* f1;
    };

    func() = default;
    func(const char* name, F0* f0) : name(name), argc(0), f0(f0) { }
    func(const char* name, F1* f1) : name(name), argc(1), f1(f1) { }
};

int foo(void* p, int v) { return 42; }

int main() {

    func fdef = { "meth1", foo };
}


И про default member initializers не забываем — C++ же, все-таки
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 21.03.2020 5:57 rg45 . Предыдущая версия . Еще …
Отредактировано 21.03.2020 5:56 rg45 . Предыдущая версия .
Отредактировано 21.03.2020 5:55 rg45 . Предыдущая версия .
Re: С++ union initialization
От: Pavel Dvorkin Россия  
Дата: 21.03.20 05:58
Оценка: 21 (1)
Здравствуйте, c-smile, Вы писали:




CS>
CS>func fdef = { "meth1", 1, {.f1 = foo} };
CS>


CS>Но чего-то не выходит каменный цветок, во всяком случае в VS2017


CS>Можно как-то победить это безобразие?


Это компилируется, если тип файла .c.
With best regards
Pavel Dvorkin
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.