Инициализация стуктуры...
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 13.07.18 15:00
Оценка:
Есть структура с указателями на функции. Типа VTBL.

Некоторые функции имеют одинаковый набор аргументов.

Хочу безопасно инициализировать глобальный экземпляр этой структуры.

Пишу (я знаю что так нельзя, но вдруг уже стало можно в VS2017):

static const impl::text_services::db_common__text_services__cfg
 g_text_services_cfg=
{
 skeep_empty_space=impl::text_services::db_common__text_services__functions::skeep_empty_space,
 skeep_liter      =impl::text_services::db_common__text_services__functions::skeep_liter,
 char_is_delimiter=impl::text_services::db_common__text_services__functions::char_is_delimiter,
 pack_text_for_sql=impl::text_services::db_common__text_services__functions::pack_text_for_sql,
 test_eol_char    =impl::text_services::db_common__text_services__functions::test_eol_char__n_rn,
 test_empty_char  =impl::text_services::db_common__text_services__functions::test_empty_char,
};//g_text_services_cfg

Ошибка компиляции.

Блин. Я наверное раньше копыта откину, чем этот проклятый C++ будет удовлетворять моим скромным хотелкам
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Инициализация стуктуры...
От: watchmaker  
Дата: 13.07.18 16:15
Оценка: 6 (1) +1
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Некоторые функции имеют одинаковый набор аргументов.

КД>Хочу безопасно инициализировать глобальный экземпляр этой структуры.
КД>Пишу …
А напиши ещё, почему ты считаешь, что это безопасно? А то из вопроса просто не очень ясно, чего же именно ты хочешь избежать.


КД>(я знаю что так нельзя, но вдруг уже стало можно в VS2017):

КД>static const impl::text_services::db_common__text_services__cfg
КД> g_text_services_cfg=
КД>{
КД> skeep_empty_space=impl::text_services::db_common__text_services__functions::skeep_empty_space,
КД> skeep_liter      =impl::text_services::db_common__text_services__functions::skeep_liter,
КД>

КД>Ошибка компиляции.

Designated initializers разшешены только в С++20 (ну и в С давным-давно ). Конечно, в clang или gcc их можно и сейчас использовать, но только как расширения С++.
Ну и точку перед именем поля нужно не забывать ставить:
g_text_services_cfg = {
    .skeep_empty_space = impl::text_services::db_common__text_services__functions::skeep_empty_space,
    .skeep_liter = impl::text_services::db_common__text_services__functions::skeep_liter,
…


Но если тебе хочется именно имя поля указывать при инициализации, то можешь использовать named parameter idiom. И это отлично комбинируется с constexpr чтобы вся работа по инициализации так и оставалась во времени компиляции.
Отредактировано 13.07.2018 16:32 watchmaker . Предыдущая версия .
Re[2]: Инициализация стуктуры...
От: EreTIk EreTIk's Box
Дата: 13.07.18 16:33
Оценка:
КД>>Хочу безопасно инициализировать глобальный экземпляр этой структуры.
КД>>Пишу …
W>А напиши ещё, почему ты считаешь, что это безопасно? А то из вопроса просто не очень ясно, чего же именно ты хочешь избежать.

Рискну предположить, что ТС опасается, что изменив порядок полей структуры (поменяв между собой поля — указатели на одинаковый прототип функции), компиляция будет успешной, но поля будут инициализированы неправильно.

Я бы решил эту проблему инициализацией при описании самой структуры, как-то так:
struct db_common__text_services__cfg
{
    skeep_empty_space_ptr skeep_empty_space{impl::text_services::db_common__text_services__functions::skeep_empty_space};
    skeep_liter_ptr skeep_liter{impl::text_services::db_common__text_services__functions::skeep_liter};
};
Re: Инициализация стуктуры...
От: Evgeny.Panasyuk Россия  
Дата: 13.07.18 16:35
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Хочу безопасно инициализировать глобальный экземпляр этой структуры.


Можно типами пометить изобразив strong typedef:
#define STRONG_TYPEDEF(FUNC, NAME)       \
    class NAME                           \
    {                                    \
        using F = FUNC;                  \
        F x;                             \
    public:                              \
        explicit NAME(F x) : x(x) {}     \
        operator F() const { return x; } \
    }                                    \
/**/

struct Table
{
    STRONG_TYPEDEF(void(*)()    , Skip       ) skip;
    STRONG_TYPEDEF(bool(*)(char), IsDelimiter) is_delimiter;
} table =
{
    Table::Skip{[]{}},
    Table::IsDelimiter{[](char x){return x == ',';}}
};

int main()
{
    table.skip();
    table.is_delimiter(',');
}
Re[3]: Инициализация стуктуры...
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 13.07.18 18:23
Оценка:
Здравствуйте, EreTIk, Вы писали:

КД>>>Хочу безопасно инициализировать глобальный экземпляр этой структуры.

КД>>>Пишу …
W>>А напиши ещё, почему ты считаешь, что это безопасно? А то из вопроса просто не очень ясно, чего же именно ты хочешь избежать.

ETI>Рискну предположить, что ТС опасается, что изменив порядок полей структуры (поменяв между собой поля — указатели на одинаковый прототип функции), компиляция будет успешной, но поля будут инициализированы неправильно.


Да, и по этой причине тоже. Спасибо.

Еще можно натупить и при определении, перепутав порядок следования значений полей.

ETI>Я бы решил эту проблему инициализацией при описании самой структуры, как-то так:

ETI>
ETI>struct db_common__text_services__cfg
ETI>{
ETI>    skeep_empty_space_ptr skeep_empty_space{impl::text_services::db_common__text_services__functions::skeep_empty_space};
ETI>    skeep_liter_ptr skeep_liter{impl::text_services::db_common__text_services__functions::skeep_liter};
ETI>};
ETI>


Не, не подходит — у меня создается два разных экземпляра этой структуры
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Отредактировано 13.07.2018 18:57 DDDX . Предыдущая версия .
Re[2]: Инициализация стуктуры...
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 13.07.18 18:28
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Designated initializers разшешены только в С++20

-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Инициализация стуктуры...
От: watchmaker  
Дата: 13.07.18 19:50
Оценка: 3 (1)
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Не, не подходит — у меня создается два разных экземпляра этой структуры

Тогда делай через named parameter. Будешь писать так:
g_text_services_cfg = db_common__text_services__cfg_builder()
 .skeep_empty_space(impl::text_services::db_common__text_services__functions::skeep_empty_space)
 .skeep_liter      (impl::text_services::db_common__text_services__functions::skeep_liter)
 .char_is_delimiter(impl::text_services::db_common__text_services__functions::char_is_delimiter)
 .pack_text_for_sql(impl::text_services::db_common__text_services__functions::pack_text_for_sql)
 .test_eol_char    (impl::text_services::db_common__text_services__functions::test_eol_char__n_rn)
 .test_empty_char  (impl::text_services::db_common__text_services__functions::test_empty_char)
;

В общем-то даже довольно похоже на изначальный вариант получается


  builder
Например можно либо вручную нормальный builder написать, либо какими-нибудь макросами нафигачить:
#define FIELD(name) \
template <class T> constexpr Self& name(const T v) { \
        Slave::name = v; \
        return *this; \
}

struct db_common__text_services__cfg_builder: db_common__text_services__cfg {
    using Slave = db_common__text_services__cfg;
    using Self = db_common__text_services__cfg_builder;
  
    // тут просто перечислить все имена полей
    FIELD(skeep_empty_space)
    FIELD(skeep_liter)
    FIELD(char_is_delimiter)
…
};
Re: Инициализация стуктуры...
От: kov_serg Россия  
Дата: 14.07.18 06:56
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>Блин. Я наверное раньше копыта откину, чем этот проклятый C++ будет удовлетворять моим скромным хотелкам

#include <stdio.h>

struct A {
    void (*seek)();
    void (*read)();
    template<class T>struct Init{};
    template<class T>A(Init<T> t) { ((T*)this)->init(); }
};

static void _read() { printf("read\n"); }
static void _seek() { printf("seek\n"); }

struct DefA : A { void init() {
    seek=_seek;
    read=_read;
}};
static const A a=A::Init<DefA>();

int main(int argc,char** argv) {
    a.seek();
    a.read();
    return 0;
}

Так хотелки не удовлетворить?
Re[2]: Инициализация стуктуры...
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 14.07.18 07:26
Оценка:
Здравствуйте, kov_serg, Вы писали:

КД>>Блин. Я наверное раньше копыта откину, чем этот проклятый C++ будет удовлетворять моим скромным хотелкам

struct DefA : A { void init() {
    seek=_seek;
    read=_read;
}};


>Так хотелки не удовлетворить?


Сложно это все

У меня нет проблем с придумыванием всяких извращенных способов инициализации.

Я хочу простой, понятный и безопасный способ.

Желательно, чтобы компилятор сразу выругался на пропущенное поле в списке инициализации.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Инициализация стуктуры...
От: kov_serg Россия  
Дата: 14.07.18 10:22
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Я хочу простой, понятный и безопасный способ.

КД>Желательно, чтобы компилятор сразу выругался на пропущенное поле в списке инициализации.
Вам не кажется это надуманной проблемой? Или ваш код на 76% состоит из подобных инициализаций?
Если да, то сделайте генератор кода для этого.
Re[4]: Инициализация стуктуры...
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 14.07.18 20:29
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>>Я хочу простой, понятный и безопасный способ.

КД>>Желательно, чтобы компилятор сразу выругался на пропущенное поле в списке инициализации.
_>Вам не кажется это надуманной проблемой? Или ваш код на 76% состоит из подобных инициализаций?
_>Если да, то сделайте генератор кода для этого.

Не кажется. Не состоит, хотя такого кода достаточно много.

Дальнейшее обсуждение наверное уже не имеет смысла — тут уже сказали что проблема будет решена в следующем стандарте плюсов.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.