Не проблема std::move
.
Проблема в том, что C ++ является статическим типизированным языком. Поэтому, если у вас есть присваивание типа
std::tuple<Formals...> to_formals{std::move(actuals)};
, где тип кортежа decltype(actuals)
равен long
, компилятор не может оценить, время компиляции, если длинное значение равно нулю, поэтому выполните преобразованиеэто указатель того же другого типа, или нет.
Для этого типа проблем C ++ 11 ввел тип для нулевых указателей (std::nullptr_t
) и новое ключевое слово, чтобы избежать NULL
(nullptr
).
Так, например, если у вас есть следующая функция
template <typename ... Formals, typename ... Actuals>
void foo (void(*)(Formals...), std::tuple<Actuals...> act)
{
std::tuple<Formals...> frm { std::move(act) };
}
и вам дана функция void(float *, int, int *)
void bar (float *, int, int *)
{ }
, вызываемая с помощью NULL
foo(&bar, std::make_tuple(&f0, 0, NULL)); // compilaton error
вы получаете ошибку компиляции (я полагаю, что вы ответили на ваш вопрос), но используете nullptr
foo(&bar, std::make_tuple(&f0, 0, nullptr)); // compile
Если вы действительно хотите / нуждаетесь в использовании NULL
вместо nullptr
лучшее, что я могу себе представить, - привести каждый элемент кортежа actuals
к типу корня формалей;что-то следующее
template <typename ... Formals, typename ... Actuals, std::size_t ... Is>
void foo_helper (void(*)(Formals...), std::tuple<Actuals...> act,
std::index_sequence<Is...>)
{
std::tuple<Formals...> frm { (Formals)std::get<Is>(act)... };
}
template <typename ... Formals, typename ... Actuals>
void foo (void(*pfunc)(Formals...), std::tuple<Actuals...> act)
{
foo_helper(pfunc, act, std::make_index_sequence<sizeof...(Actuals)>{});
}
Теперь скомпилируйте также
foo(&bar, std::make_tuple(&f0, 0, NULL));
- РЕДАКТИРОВАТЬ -
ОП запрашивает
Не могли бы вы рассказать подробнее об используемой index_sequence. Кроме того, действительно ли нам нужна вспомогательная функция или это можно сделать без этого
Индексы std::index_sequence
необходимы для извлечения значений из кортежа act
;к сожалению, пара std::index_sequence
/ std::make_index_sequence
представлена в C ++ 14, но, если вам это нужно в C ++ 11, существует множество альтернативных реализаций C ++ 11.
К сожалению,последовательность индексов в std::index_sequence
требует создания std::make_index_sequence
из sizeof...()
, поэтому необходим вызов функции, поэтому необходима функция foo_helper()
.
Исключение.
Если ваш act
кортеж как точно один элемент для каждого типа, вы можете (начиная с C ++ 14) просто написать
std::tuple<Formals...> frm { (Formals)std::get<Actuals>(act)... };
непосредственно внутри foo()
, не определяя /вызов foo_helper()
.
Но предложение о запрещении столкновений - большой предел, ИМХО.