#c
#c
Вопрос:
Этот вопрос похож на другие, которые задавались здесь, но с небольшой изюминкой. У меня есть обычная функция примерно такого типа:
void Bar(std::initializer_list<Base*> objects);
Теперь я хочу создать шаблон функции, который обертывает каждый параметр в тип, производный от Base
и передает их функции выше. Что-то вроде:
template <class... Params> void Foo(Params... parameters)
{
Bar({amp;Wrapper<Params>(parameters)...});
}
(Класс Wrapper
специализирован для различных типов.) Этот код фактически компилируется в MSVC, но компилятор выдает предупреждение, потому что я беру адрес rvalue (который запрещен стандартом). Есть ли простой, соответствующий стандартам способ добиться того же? (Я думаю, что я могу сделать это с помощью tuples, integer_sequences и вспомогательной функции, но я бы хотел избежать этого, если это возможно.)
Комментарии:
1. Создайте
tuple<Wrapper<Params>...>
, а затем возьмите адреса элементов кортежа?2. Кортеж, безусловно, помогает мне в этом, но есть ли способ получить адрес каждого элемента кортежа, не проходя через integer_sequence?
3. Вместо списка указателей инициализатора вы можете использовать список ссылок инициализатора rvalue?
4. Я в это не верю. Массивы ссылок являются незаконными.
Ответ №1:
Проблема Wrapper<T>
в том, что экземпляры должны существовать по некоторому адресу. Самый простой способ сделать это — создать std::tuple<Wrapper<Params>...>
экземпляр. Раздражает то, что вам приходится извлекать содержимое обратно с помощью std::get<N>
. В C 14 std::index_sequence
существует, чтобы помочь вам в этом вопросе.
template <class... Params, std::size_t... Idx>
void FooImpl(std::tuple<Wrapper<Params>...>amp; tup, std::index_sequence<Idx...>)
{
Bar({ (amp;std::get<Idx>(tup))... });
}
template <class... Params>
void Foo(Params... parameters)
{
std::tuple<Wrapper<Params>...> tup(Wrapper<Params>(parameters)...);
FooImpl(tup, std::make_index_sequence<sizeof...(Params)>());
}
Если вы Bar
используете const Wrapper<T>*
s, другим вариантом является использование правил C constant ref в ваших интересах.
template <class... Params>
void FooImpl(const Wrapper<Params>amp;... parameters)
{
Bar({ (amp;parameters)... });
}
template <class... Params>
void Foo(Params... parameters)
{
FooImpl(Wrapper<Params>(parameters)...);
}
Комментарии:
1. Как это бывает, Bar может принимать оболочку const . Это работает довольно хорошо. Хотя, по правде говоря, решение integer_sequence не так уж плохо, теперь, когда я его вижу. Спасибо за вашу помощь.