Назовите правильную специализацию шаблона для каждого типа вариационного шаблона. - PullRequest
1 голос
/ 03 июля 2019

У меня есть функция foo(), которая принимает список типов T... и внутри вызывает другую (шаблонную) функцию с именем do_stuff() для каждого переданного элемента вектора. Более конкретно, мы зациклимся на векторе(длины sizeof...(T)) и хотел бы вызвать do_stuff<Ti>() для vector[i], где Ti - это i -й тип в T...

Информация доступна во время компиляциитак что я думаю, что это возможно, но как мы это делаем красиво?

#include <iostream>
#include <string>
#include <vector>
#include <cassert>

template <typename T>
T do_stuff(int param);

template <>
int do_stuff(int param)
{
    return int(100);
}

template <>
std::string do_stuff(int param)
{
    return std::string("foo");
}

template <typename... T>
void foo(const std::vector<int>& p)
{
    assert(p.size() == sizeof...(T));
    for (int i = 0; i < p.size(); ++i)
    {
        // Won't compile as T is not specified:
        //do_stuff(p[i]);
        // How do we choose the right T, in this case Ti from T...?
    }
}

int main()
{
    std::vector<int> params = { 0,1,0,5 };
    foo<int, std::string, std::string, int>(params);
}

Ответы [ 2 ]

6 голосов
/ 03 июля 2019

Вы можете использовать C ++ 17 кратное выражение:

template <typename... T>
void foo(const std::vector<int>& p)
{
    assert(p.size() == sizeof...(T));

    std::size_t i{};
    (do_stuff<T>(p[i++]), ...);
}

живой пример на godbolt.org


Кроме того, вы можете избежать изменяемой переменной i с помощью std::index_sequence:

template <typename... T>
void foo(const std::vector<int>& p)
{
    assert(p.size() == sizeof...(T));

    [&p]<auto... Is>(std::index_sequence<Is...>)
    {
        (do_stuff<T>(p[Is]), ...);
    }(std::index_sequence_for<T...>{});
}

живой пример на godbolt.org

4 голосов
/ 03 июля 2019

Как насчет следующего?

template <typename ... T>
void foo (std::vector<int> const & p)
{
    assert(p.size() == sizeof...(T));

    using unused = int[];

    std::size_t  i{ 0u };

    (void)unused { 0, ((void)do_stuff<T>(p[i++]), 0)... };
}

Если вы можете использовать C ++ 17, см. Ответ Витторио Ромео для более элегантного и сжатого решения.

...