是否有任何理由使模板模板参数不可变
Is there any reason to make a template template parameter non variadic?
如果我希望模板模板参数有一个参数,那么我可以如下声明:
template<template<typename> class T>
struct S {
T<int> t_;
//other code here
}
然而,如果我稍后想提供一个模板模板参数,该参数采用两个参数,其中第二个参数具有默认值(如std::vector)T<int> t_;
仍然有效,但模板与template<typename> class T
不匹配。我可以通过将template<typename> class T
制作成可变模板template<typename...> class T
来解决这个问题。现在我的代码更加灵活了。
我应该让我所有的模板模板参数在未来变化吗?我有什么不应该这样做的原因吗(假设由于其他原因,我的代码已经需要C++11支持)?
首先,文档。如果参数是可变的,用户现在需要检查其他来源,以发现它确实需要一个模板参数。
第二,及早检查。如果您不小心在S
中向T
传递了两个参数,编译器不会告诉您它是否是可变的,直到用户真正尝试使用它
第三,错误消息。如果用户传递了一个实际上需要两个参数的模板,那么在可变版本中,编译器会在S
实例化T
的那一行给他一条错误消息,所有的回溯都在这一行之间。在固定版本中,他在实例化S
时会得到错误。
第四,这是不必要的,因为模板别名也可以解决这个问题。
S<vector> s; // doesn't work
// but this does:
template <typename T> using vector1 = vector<T>;
S<vector1> s;
所以我的结论是,不要让事情变得多变。实际上,你并没有获得灵活性,你只是减少了用户必须编写的代码量,代价是可读性较差。
如果你已经知道你很可能需要它,你应该添加它。否则,你就不需要它(YAGNI),所以它会添加更多的东西来维护。这与最初使用模板参数的决定类似。特别是在TDD类型的环境中,您只会在需要时进行重构,而不是过早地进行抽象。
将猖獗的抽象应用于应用程序。相反,这需要开发人员只将抽象应用于程序的那些部分表现出频繁变化抵制过早的抽象是与抽象本身一样重要
Robert C.Martin第132页,C#中的敏捷原则、模式和实践
正如您自己指出的那样,可变模板的好处是真实的。但只要对它们的需求仍然是推测性的,我就不会添加它们。
- 函数在可变参数模板的实例化期间不可见
- 可变参数函数模板不能很好地使用 std::function 作为参数
- 以下可变参数模板行为是否不一致?
- 用户定义的转换不适用于可变参数函数参数?为什么不呢?
- 在可变参数模板函数中存储参数而不使用 boost::any
- 具有右值引用,而不是使用可变参数模板转发引用
- 参数包推导不一致 int 和 int& 在可变参数模板化成员函数中创建运行成员函数的线程
- 为什么C++可变参数模板不接受 iostream 值作为参数?
- C++具有可变参数包的函数的部分模板参数推导会在 Clang 和 MSVC 中产生不明确的调用
- 不明确的可变参数类成员访问
- 摆脱可变参数模板递归基本情况下不必要的类
- 演绎指南和具有可变参数模板构造函数的可变参数类模板 - 参数包长度不匹配
- 带有可变参数的嵌套宏在GCC中编译,但在MSVC中不编译
- C++ 模板可变参数类构造函数使用参数包,但函数不
- 为什么可变参数模板在模板介绍中不起作用,但在要求子句中起作用?ConceptName{T,U,V,W} <-- template<typename ...T>
- 可变参数模板化构造函数不接受 x 参数
- 为什么我们不能在模板专业化的开始/中间使用可变参数模板(以及如何模拟)?
- 如何在参数包不是最后一个参数的C++中编写可变参数模板函数?
- 如何检测我何时向可变参数函数传递"std::string"而不是"c_str()"
- 递归调用可变参数模板函数重载时的不明确调用