我正在测试可变函数,希望我能用它来解决我需要创建一个包含任意数量参数的对象的问题。它实际上工作正常,但传递给函数 createObject 的参数需要是动态的。在下面的示例中,只有两个参数传递给构造函数,但在最终程序中,参数传递的数量和顺序应该是任意的(参数总是具有Param类型)。
我似乎找不到这样做的方法。任何帮助,想法等将不胜感激。
PS:我在Stackoverflow上发现了几个类似的问题,但它们已经过时了,并没有提供任何可接受的答案。
struct Vec3f { float x, y, z; };
struct Vec2f { float x, y; };
template<class T>
struct Param
{
static const std::size_t size = sizeof(T);
Param(const std::string &n) : name(n) {}
std::string name;
};
typedef Param<Vec3f> ParamFloat3;
typedef Param<Vec2f> ParamFloat2;
void parseParameters(std::size_t &stride) {}
template<class T, typename ... Types>
void parseParameters(std::size_t &stride, const Param<T> &first, Types ... args)
{
stride += first.size;
parseParameters(stride, args ...);
}
template<class T, typename ... Types>
void createObject(const Param<T> &first, Types ... args)
{
std::size_t stride = 0;
parseParameters(stride, first, args...);
}
int main(int argc, char **argv)
{
ParamFloat3 test1("T1");
ParamFloat2 test2("T2");
createObject(test1, test2); // would like to make this dynamic
return 0;
}
答案 0 :(得分:0)
所有类型的模板编程(包括可变参数模板)都在编译时解析。您需要将容器(例如std::vector
)传递给您的函数。
修改:如果您需要传递不同类型的参数(Param<Vec3f>
和Param<Vec2f>
实际上严格不同,尽管来自同一模板),您需要依靠多态性。为所有参数提供相同的基类,并使用虚函数或dynamic_cast
来恢复正确的行为。
实现这一目标的最安全方法(并避免对象切片)将使用std::vector<std::unique_ptr<Param>>
,其中Param是您的基类。
答案 1 :(得分:0)
不是将第一个参数检查为Param<T>
,而是可以推导出整个参数:
template<class Head, class... Tail>
void parseParameters(std::size_t& stride, Head&& head, Tail&&... tail)
{
stride += head.size;
parseParameters(stride, std::forward<Tail>(tail)...);
}
template<class... Args>
void createObject(Args&&... args)
{
std::size_t stride = 0;
parseParameters(stride, std::forward<Args>(args)...);
}
如果您打算根据类型使用不同的功能,也可以禁用不同的重载并启用其他重载。