操作可变参数模板参数列表

问题描述 投票:-1回答:1

我想在模板参数列表中操作某些类型的数据。在我的情况下,我想检查一些元素是否是某种Iterable,如果有的话,那么我想在它们上使用std::advance

这就是我的想法:(好吧,它显然不会编译,但给你正确的想法,我想在这里实现)

#include <typeinfo>
#include <thread>

template<class _Func, class Iterator, class... _Args>
void
start(_Func pFunc, const Iterator begin, const Iterator end, _Args&&... args)
{
    Iterator pt = begin;
    Iterator ptNext = begin;
    for (unsigned int i = 0; i < this->nThreads(); i++)
    {
        std::advance(ptNext, partialSize);
        this->getThreads(i) = std::thread(pFunc, pt, ptNext, std::forward<_Args>(args)...);
        pt = ptNext;
        [](...){}((typeid(args) == typeid(Iterator) ? std::advance(args, partialSize) : false)...);
    }
}

我认为问题是(可能?),参数列表在编译时扩展然后它会看到,我想在某些东西上使用std::advance,甚至可能不是Iterable类型。

在上面的代码中,beginend是数据序列的迭代器,而partialSize变量告诉我,一个线程应该只处理序列的一部分。

所以目标是,如果任何其他Iterable类型通过参数列表传递,请说:std::vector<>::iteratorstd::list<>::iterator甚至是double*,那么我想std::advance他们。

这个问题有什么解决方案吗?我能实现这样的目标吗?

c++ templates variadic-templates variadic-functions
1个回答
1
投票

我已经实现了一个函数来推进传递给它的所有迭代器。它只是忽略任何其他类型的参数。

该代码需要C ++ 17,但可以移植到早期版本的标准。

#include <iterator>
#include <type_traits>

template <class T, class = void>
struct is_iterator : std::false_type {};

template <class T>
struct is_iterator<T, std::void_t<typename std::iterator_traits<T>::iterator_category>> : std::true_type {};

template <class Distance, class T>
void advance_if_iterable_impl(Distance n, T& t)
{
    if constexpr (is_iterator<T>::value)
        std::advance(t, n);
}

template <class Distance, class... Args>
void advance_if_iterable(Distance n, Args&... args)
{
    (advance_if_iterable_impl(n, args), ...);
}

#include <iostream>

int main()
{
    int i = 42;
    const char* str = "Hello World!\n";

    advance_if_iterable(2, i, str);

    // `int` isn't an iterator, it stays the same
    std::cout << i << '\n';
    // `const char*` is a random iterator, so it was advanced by two
    std::cout << str;

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.