Разверните std :: vector в пакет параметров - PullRequest
1 голос
/ 31 октября 2019

У меня есть методы со следующей подписью:

void DoStuff(int i);
void DoStuff(int i, k);
void DoStuff(int i, int k, int l);

У меня есть метод, из которого я хотел бы вызвать методы DoStuff следующим образом:

void CallDoStuff(const std::vector<int>& vElements) {
  // What magic is supposed to happen here to make vElements an expandable pack?
  DoStuff(vElemets...);
}

Есть ли шансдля достижения этой цели? Правильно ли использовать std :: index_sequence? Если да, не могли бы вы дать мне простой пример, как применить это к моей проблеме?

Ответы [ 3 ]

0 голосов
/ 31 октября 2019

Проблема в том, что из std::vector вы не можете - скомпилировать время - извлечь значение size().

вы можете получить то, что вы хотите, только если вы передадите в качестве известного значения времени компиляции CallDoStuff() количество элементов, которое вы хотите использовать из вектора.

Вы можете передать его как, например,, значение шаблона.

Используя вспомогательную функцию, вы можете написать что-то вроде следующего:

template <std::size_t ... Is>
void CallDoStuff (std::vector<int> const & vElements,
                  std::index_sequence<Is...> const &)
 { DoStuff(vElements[Is]...); }

template <std::size_t N>
void CallDoStuff (std::vector<int> const & vElements)
 { CallDoStuff(vElements, std::make_index_sequence<N>{}); }

Вызов может быть чем-то вроде

CallDoStuff<5u>(v);

Если вы можете использоватьstd::array, вместо std::vector, ответ другой: вы можете извлечь size() из самого типа, поэтому

template <std::size_t N, std::size_t ... Is>
void CallDoStuff (std::array<int, N> const & vElements,
                  std::index_sequence<Is...> const &)
 { DoStuff(vElements[Is]...); }

template <std::size_t N>
void CallDoStuff (std::array<int, N> const & vElements)
 { CallDoStuff(vElements, std::make_index_sequence<N>{}); }

, который можно вызывать без объяснения N, следующим образом

std::array<int, 5u>  arr { 2, 3, 5, 7, 11 };

CallDoStuff(arr); // no more <5u>

Конечное примечание: обратите внимание, что std::make_index_sequence и std::index_sequence доступны только начиная с C ++ 14. В C ++ 11 их нужно каким-то образом заменить.

0 голосов
/ 04 ноября 2019

Это возможно, если вы указали верхнюю границу для количества аргументов.

Использование Реализация Xeo из std::index_sequence для C ++ 11:

template <unsigned... Idx>
void trampoline(const std::vector<int>& vElements, seq<Idx...>) {
    return DoStuff(vElements[Idx]...);
}

template <std::size_t Arity>
void trampoline(const std::vector<int>& vElements) {
    return trampoline(vElements, typename gen_seq<Arity>::seq{});
}

template <unsigned... Idx>
void CallDoStuff(const std::vector<int>& vElements, seq<Idx...>) {
    using trampoline_t = void (*)(const std::vector<int>&);
    constexpr trampoline_t trampolines[]{
        trampoline<Idx>...
    };
    trampolines[vElements.size()](vElements);
}

template <std::size_t Max>
void CallDoStuff(const std::vector<int>& vElements) {
    assert(vElements.size() <= Max);
    return CallDoStuff(vElements, typename gen_seq<Max + 1>::seq{});
}

Посмотреть в прямом эфире на Wandbox

0 голосов
/ 31 октября 2019

Этого нельзя сделать, вызов метода шаблона связан во время компиляции, но std::vector не знает, сколько элементов он содержит до времени выполнения, поэтому невозможно объединить эти два понятия.

DoStuff(vElemets...);

Здесь компилятор должен выбрать правильную реализацию в зависимости от того, сколько элементов vElements имеет. В этом типе мышления вы видите недостаток, поскольку std::vector - это просто объект, который может содержать любое количество элементов в момент вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...