使用scopedptr解压缩varadic模板

unpack variadic template with scoped_ptr

本文关键字:模板 varadic 解压缩 scopedptr 使用      更新时间:2023-10-16

我使用的是可变模板,我想找到一种很好的方法来解压我的参数

template <typename kernel_type, typename ...kernel_types>
class MetaKernel : public MyKernel<kernel_type, kernel_types...> {
public:
    MetaKernel (
        unsigned int m,
        unsigned int n,
        const kernel_type& kernel_,
        const kernel_types&... kernels_
    ) :
        MyKernel<kernel_type, kernel_types...>(m, n)
    {
        Ks.set_max_size(sizeof...(kernel_types));
        Ks.set_size(sizeof...(kernel_types));
        // for each kernels_, add a MyObsKernel to Ks
        // Ks[sizeof...(kernel_types)].reset((new MyObsKernel<kernel_type, kernel_types...>(kernels_, prototypes_, m, n))...);
    }
private:
    array < scoped_ptr < MyObsKernel<kernel_type, kernel_types...> > > Ks;
}

从文档中(http://en.cppreference.com/w/cpp/language/parameter_pack),我看到了如何像这样打开包装:

int dummy[sizeof...(Ts)] = { (std::cout << args, 0)... };

但当我处理scope_ptr表时,我需要用"重置"来初始化它。所以我的解决方案不起作用。如何使用scope_ptr解压缩参数?

谢谢你的帮助,Jerome

您可以使用初始化器列表初始化std::array。以下内容可能会有所帮助:https://ideone.com/PTwatb

MetaKernel (unsigned int m, unsigned int n, const kernel_type& kernel_, const kernel_types&... kernels_) :
    MyKernel<kernel_type, kernel_types...>(m, n),
    Ks({scoped_ptr<MyObsKernel<kernel_type, kernel_types...> >(new MyObsKernel<kernel_type, kernel_types...>(kernels_, kernel_, m, n))...})
{
}

正如我在评论中所说,您的问题是不完整的。我知道Ks是大小为N = sizeof...(kernel_types)std::array,并且您希望对每个元素调用reset()。如果是这样,这里有一个解决方案:

struct _do { template<typename... A> _do(A&&...) { } };
template <typename kernel_type, typename ...kernel_types>
class MetaKernel : public MyKernel<kernel_type, kernel_types...>
{
    using Base = MyKernel<kernel_type, kernel_types...>;
    using Obs  = MyObsKernel<kernel_type, kernel_types...>;
    static constexpr size_t N = sizeof...(kernel_types);
public:
    MetaKernel (
        unsigned int m,
        unsigned int n,
        const kernel_type& kernel_,
        const kernel_types&... kernels_
    ) : Base(m, n)
    {
        reset(std::make_integer_sequence<size_t, N>(), m, n, kernels_...);
    }
private:
    template<size_t... I>
    void reset (
        std::integer_sequence<size_t, I...>,
        unsigned int m,
        unsigned int n,
        const kernel_types&... kernels_
    )
    {
        _do{Ks[I].reset(new Obs(kernels_, /*prototypes_,*/ m, n))...};
    }
    array <scoped_ptr <Obs>, N> Ks;
};

我正在使用辅助对象_do和C++14的特征std::integer_sequencestd::make_index_sequence。如果这不可用,您可以在此处查看Range,其中还解释了_do

您需要除构造函数之外的第二个函数来推导索引包I...,并使用它与参数kernels_...对齐,以便在Ks的一个元素上的reset()的一个调用中使用每个参数。

如果您有更多这样的拆包操作,最好在整个类中都有I...可用,并直接使用它。然后,您只需要第二个MetaKernelImpl类,而不是为每个函数添加第二个版本。这个类将有一个额外的模板参数,专门用于某些推导包size_t... Istd::integer_sequence<size_t, I...>。再次,看看这里的Caller,看看如何做到这一点。