在可变参数模板函数中存储参数而不使用 boost::any



我用变量模板函数的 C++11 编写了以下短代码,并将参数存储到 boost::any 类型的向量中。它运行良好,但我不想使用 boost::any 库(由于某些限制(。

#include <boost/any.hpp>
template <class Var, class... Args>
void cpp_for(Var *variable, uint32_t numParams, Args... args)
{
std::vector<boost::any> arguments{args...};
if(arguments.size() != numParams)
throw std::runtime_error("mismatch");
for(uint32_t i = 0; i < numParams; ++i)
variable[i] = *(boost::unsafe_any_cast<Var>(&arguments[i]));
}

我像这样调用函数:

cpp_for(myObj->var, 3, 0x56, 0x23, 0x10);

cpp_for(myObj2->var, 2, myObj2->var2, myObj2->var3);

有没有办法存储参数并一一处理它们,而无需 boost::any?

编辑1:我的参数都是同一类型。

编辑2:由于上面代码的目标是assignment,因此创建一个额外的数据结构(向量(是没有用的。查看"Nir Friedman"的答案,以获得更有效的解决方案。

您可以使用std::common_type,例如:

template <class Var, class... Args>
void CPP_FOR(Var *variable, uint32_t numParams, Args... args)
{
std::vector<std::common_type_t<Args...>> arguments{args...};
// do stuff with arguments
}

您还可以删除numParams和运行时检查,因为如果没有通用类型,这将在编译时失败。如果你只想迭代参数,向量可能是矫枉过正......所以像这样:

template <class Var, class... Args>
void CPP_FOR(Var *variable, Args... args)
{
std::common_type_t<Args...> arguments[]{args...};
for(size_t i = 0; i < sizeof...(Args); ++i)
variable[i] = /* ... */;
}

请注意,如果sizeof... (Args)为 0,则这两种操作都将失败,即您只使用Var*调用 - 如有必要,您可能需要单独处理这种情况。

假设你的目标实际上只是执行赋值,你根本不需要向量。

template <class Var, class... Args>
void CPP_FOR(Var *variable, uint32_t numParams, Args... args)
{    
if(sizeof...(Args) != numParams)
throw std::runtime_error("mismatch");
int i = 0;
int temp [] = {(variable[i++] = args, 0)...};
}

现场示例:http://coliru.stacked-crooked.com/a/710a09332bf2c965

与创建难以优化的向量相比,这种开销不仅为零,而且还允许以最自然的方式进行隐式转换。其他方法可能会有惊喜。

如果你知道至少会有一个参数,你可以用稍微不同的方式编写你的函数来做到这一点。

template <typename Arg, typename... Args>
void cpp_for(Arg arg, Args... args) {
std::vector<Arg> vec { arg, args... };
// ...
}

但是,如果参数列表为空,这将失败。最简单的解决方案是简单地添加不需要参数的cpp_for的第二个重载。

void cpp_for() {
std::vector<SomeDefaultType> vec; // Empty vector
// ...
}

当然,只有在使用零参数调用函数有意义时才需要这样做。

请记住,如果ArgsArg最终不是同一类型,则此方法将给出非常悲惨的错误消息。这可以通过一些 小心使用static_assert.

最新更新