Попытка обойти ошибки компиляции std :: bind

Раньше я использовал std :: bind, и я думаю, что близок к этому использованию, но не совсем так, и я не знаю, как исправить ошибку компиляции.

Конечная цель - это средний массив указателей на небольшое количество функций с разными параметрами в каждом элементе массива. На данный момент у меня есть только одна функция и одна запись в таблице. Если я сумею понять это правильно, я думаю, что смогу решить все остальное. Я хочу использовать std :: function, чтобы я мог помещать различные параметры в массив.

Вот объявление пока только одной функции:

static Get *MakeGArrayStatic(void *Subscript, const void **array, unsigned int sizeOfArray);

Вот объявление единственного указателя, типичного для массива:

typedef std::tr1::function<Get *(void *, const void**, unsigned int)> GetMaker;
static GetMaker *gm1;

Вот определение указателя:

Get::GetMaker *Get::gm1 = std::tr1::bind(&MakeGArrayStatic, &OutMsg::CurrentSeverity, FacSevTbls::SyslogSeveritiesForMessages, FacSevTbls::NumberOfTrueSeverities);

(Get - это класс, CurrentSeverity - это перечисление, SyslogSeveritiesForMessages - это const char **, а NumberOfTrueSeverities - это size_t.)

Ошибка, которую я получаю (VS 2010),

ошибка C2440: 'инициализация': невозможно преобразовать из 'std :: tr1 :: _ Bind ‹_Result_type, _Ret, _BindN>' в 'Get :: GetMaker *' с [_Result_type = Get *, _Ret = Get *, _BindN = std: : tr1 :: _ Bind3, SyslogEnums :: SeverityEnum *, const char **, size_t>] Нет доступного определяемого пользователем оператора преобразования, который мог бы выполнить это преобразование, или оператор не может быть вызван

Кто-нибудь может указать, где я ошибаюсь?


person Charles    schedule 22.09.2018    source источник
comment
Почему бы вообще не использовать лямбда-функции вместо std::bind?   -  person πάντα ῥεῖ    schedule 23.09.2018
comment
почему gm1 указатель?   -  person kmdreko    schedule 23.09.2018
comment
Потому что я нацелен на два компилятора, а другой, к сожалению, не поддерживает лямбда-функции. (То же самое и с VS 2010, но было бы легко обновить VS. Не то же самое с другим компилятором.) Но хорошее предложение. Спасибо.   -  person Charles    schedule 23.09.2018
comment
@kmdreko Я считаю, что gm1 - это указатель на функцию. Это мое намерение. Это будет вызываться с помощью (gm1) (). Указатели в конечном итоге будут массивом указателей. Я просто попытался убрать *, и компилятор действительно взбесился.   -  person Charles    schedule 23.09.2018
comment
Но std::bind() не возвращает указатель, не так ли? Он возвращает вызываемый объект по значению (которое вы можете присвоить своему std::function()).   -  person PlinyTheElder    schedule 23.09.2018
comment
@PlinyTheElder ну, я тут борюсь. Что я должен кодировать? Я просто попробовал * gm1 = & bind (... и это тоже неправильно.   -  person Charles    schedule 23.09.2018
comment
@ Чарльз: нет, это должно быть GetMaker func = std::bind( ...your params here... ). И тогда вам нужно правильно настроить параметры.   -  person PlinyTheElder    schedule 23.09.2018
comment
@PlinyTheElder вот и все! Когда я изменил * gm1 на простой gm1, компилятор пришел в ярость, но первая ошибка заключалась в том, что не удалось присвоить char ** значение void **, поэтому я выполнил приведение, и он компилируется чисто.   -  person Charles    schedule 23.09.2018
comment
@PlinyTheElder спасибо. Как отметить ваш комментарий как ответ?   -  person Charles    schedule 23.09.2018
comment
@ Чарльз: все в порядке, я рад, что он работает. Как только вы сохраните результат std :: bind () в std :: function, вы можете передать объект std :: function по ссылке или значению, как обычно.   -  person PlinyTheElder    schedule 23.09.2018


Ответы (1)


Еще раз спасибо @PlinyTheElder, но я думаю, что мы оставили вопрос «официально» без ответа. Завершая цикл, вот объявления с первым вырезом в массиве функций:

static Get *MakeGArrayStatic(void *Subscript, const char **array, size_t sizeOfArray);
static Get *MakeGStatic(void *field, size_t sizeOfField);
typedef std::tr1::function<Get *()> GetMaker;
static GetMaker gm[];

и вот определение массива на данный момент:

std::tr1::function<Get *()> Get::gm[] = { 
    std::tr1::bind(&Get::MakeGArrayStatic, &OutMsg::CurrentSeverity, FacSevTbls::SyslogSeveritiesForMessages, FacSevTbls::NumberOfTrueSeverities), 
    std::tr1::bind(&MakeGStatic, Msg::MessageID, 8) } ;

А вот тривиальный пример вызова функции:

    Get *g = Get::gm[0]();

Получилось лучше, чем я ожидал. Я представлял себе, что все «маленькие функции» должны иметь одну и ту же сигнатуру (например, перегрузки). Компилируется чисто на обоих целевых компиляторах. (Еще не проверял исполнение, но уверен.) Еще раз спасибо!

Обновление: да, выполняется.

person Charles    schedule 23.09.2018