不使用模板参数的模板类
Template class with no use of template argument
我在这样定义的类上遇到过很多次错误
class PureVirtualClass
{
virtual int foo() = 0;
virtual bool bar() = 0;
}
template <class T> class ImplClass : public virtual PureVirtualClass
{
virtual ~ImplClass(){};
int foo() { return 42;}
bool bar() { return true;}
//several other method having nothing to do with T
}
这种"设计"经常出现,我想最初的开发人员知道他在做什么,将ImplClass
定义为模板类,但没有对模板参数T
的任何引用。我自己的c++模板知识有点有限。
这有好处吗?还是只是一个困惑的程序员?
对于被模板化但不依赖于参数的类来说,这是一个好处。大多数情况下,你会看到这样的东西来为模板元编程定义(空)标记结构:
template <class X>
struct some_tag {};
一般来说,像您这样的类的好处是,虽然您在每个类中都有相同的功能,但它们是不同的类,您不能将其中一个复制到另一个中,即ImplClass<int>
类型的对象与ImplCalss<float>
类型的另一个对象不兼容。
Arne提到的这个想法有很多有用的例子。例如,看看非常基本的元组实现,这就是单个元组元素的定义方式:
template <size_t N, typename T>
class TupleElem
{
T elem;
public:
T& get() { return elem; }
const T& get() const { return elem; }
};
它是在N
上模板化的,没有依赖它。为什么?因为元组实现
template <size_t... N, typename... T>
class TupleImpl <sizes <N...>, T...> : TupleElem <N, T>...
{
//..
};
导出多个这样的元素,每个元素都有一个唯一的N
,用作标识符。如果没有它,如果参数包T...
中的两个元素类型相同,TupleImpl
将两次派生同一类。在这种情况下,对元素的随机访问都不起作用(通过对适当的TupleElem
基类的函数get()
的显式调用,这将是不明确的),也不起空基优化作用(通过为空类型专门化TupleElem
T
到而不具有类型T
的数据成员)。
这是一个真实的用例,以及std::tuple
是如何通过clang实现的。当然,像TupleElem
这样的类将是一个隐藏的实现细节,而不是接口的一部分。例如,gcc遵循完全不同的递归类设计。
通常,您需要研究上下文,其中使用类来理解设计器的意图。
也许开发人员只是懒得将类拆分为.h和.cpp文件?
如果不使用模板,如果在多个编译单元中使用类,则会发生链接器错误。当使用模板时,链接器通常会在链接时丢弃模板的重复实例(或以不同的方式处理问题)。
虽然这可能是"开发人员为什么要这样做"的答案,但如果问题是"我应该在什么时候引入从未使用过的模板参数",我不建议这样做(请参阅其他答案)。尽管将代码拆分为.h和.cpp很烦人(尤其是用于Java或C#等语言时),但这是常见的C++方式。而且它肯定比仅为此目的使用模板更容易阅读/理解。此外,它还降低了类的使用的可读性。
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 使用指向成员的指针将成员函数作为参数传递
- 没有名称的C++模板参数
- 如何将enable-if与模板参数和参数包一起使用