动机:我需要为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 *
传递给派生类,并在那时将其转换回适当的位置重载呼叫。缺点:这种技术很难保持类型安全,并最大程度地减少了最终用户需要做的工作。
现在,我倾向于实现这些替代方案中的第一个,并进行一些性能测试以将其与我的工作版本进行比较,但是如果我缺少某种清洁剂,我会很乐意。
答案 0 :(得分:4)
您的实现适合C ++ 14。
C ++ 17允许可变参数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...;
};