动机:我需要为C ++ 17库构建基类,该基类将根据用户在编译时识别的类型为虚拟函数提供重载。基本上,当在基类上调用函数的特定重载时,我想确保在派生类中调用了正确的版本。我的最初本能是构建虚拟模板函数,但是C ++当然不允许这样做,因为编译器将不知道要在虚拟函数表中放入哪个版本。但是,由于我将在编译时了解所有类型,因此是否有可能使基类本身成为可变参数模板,并使用模板参数构建所需的虚拟函数的重载版本集?
折叠表达式是正确的,因为它们不能用于声明函数。递归模板似乎很有希望,但是我担心基类的继承链较长会导致性能下降。这是我的工作代码:
template <typename... Ts> class MyClass;
template <typename T, typename... Ts>
struct MyClass<T, Ts...> : public MyClass<Ts...> {
using MyClass<Ts...>::MyFunction;
virtual bool MyFunction(T in) { return true; }
};
template <>
struct MyClass<> {
virtual bool MyFunction(...) { return false; }
};
这种技术应该足够吗?还是有人对我如何实现这一目标有其他想法?
我的其他想法包括:
限制可以处理和启用的模板参数的数量(如果每个重载基于参数列表是否足够长以包含它)。缺点:此技术将是对类型数量的任意限制。
使用可变参数宏来构建类。缺点:这种技术会令人困惑且不雅。
创建一个函数,为基类中的ID编号分配类型,将其类型与ID一起传递给派生类void *
,并在那时将其转换回以进行适当的重载调用。缺点:要保持类型安全并最大程度地减少最终用户需要完成的工作量,此技术将非常棘手。
现在,我倾向于实现这些替代方案中的第一个,并进行一些性能测试以将其与我的工作版本进行比较,但是如果我缺少某种清洁剂,我会很乐意。
您的实现适合C ++ 14。
C ++ 17允许variadic using
,以避免递归:
template <typename T>
struct MyClassImpl
{
virtual ~MyClassImpl() = default;
virtual bool MyFunction(T in) = 0; // or { return true; }
};
template <typename... Ts>
struct MyClass : public MyClassImpl<Ts>...
{
using MyClassImpl<Ts>::MyFunction...;
};
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句