如何将可变参数函数模板中的每个参数转换为另一种类型并获取其地址?

时间:2016-10-14 01:24:24

标签: c++

这个问题与此处提出的其他问题类似,但有一点小问题。我有一个像这样的常规函数​​:

void Bar(std::initializer_list<Base*> objects);

现在我想创建一个函数模板,它将每个参数包装在一个派生自Base的类型中,并将它们传递给上面的函数。类似的东西:

template <class... Params> void Foo(Params... parameters)
{
    Bar({&Wrapper<Params>(parameters)...});
}

(类Wrapper专门用于各种类型。)此代码实际上在MSVC中编译,但编译器发出警告,因为我采用了右值的地址(标准不允许) 。是否有一种简单,符合标准的方式来实现同样的目标? (我想我可以使用元组,integer_sequences和辅助函数来做到这一点,但是如果可能的话,我想避免这种情况。)

1 个答案:

答案 0 :(得分:2)

问题是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>...>& tup, std::index_sequence<Idx...>)
{
    Bar({ (&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>*,则另一个选择是使用C ++的常量参考规则。

template <class... Params>
void FooImpl(const Wrapper<Params>&... parameters)
{
    Bar({ (&parameters)... });
}

template <class... Params>
void Foo(Params... parameters)
{
    FooImpl(Wrapper<Params>(parameters)...);
}