为什么无法重载类模板
Why is it not possible to overload class templates?
阅读这个问题让我想知道:不允许类模板重载是否有技术原因?
通过重载,我的意思是有几个具有相同名称但不同参数的模板,例如
template <typename T>
struct Foo {};
template <typename T1, typename T2>
struct Foo {};
template <unsigned int N>
struct Foo {};
编译器设法处理重载的函数和函数模板,是否可以将相同的技术(例如名称重整)应用于类模板?
起初,我认为在单独使用模板标识符时可能会导致一些歧义问题,但唯一可能发生的情况是在将其作为模板模板参数传递时,因此可以使用参数的类型来选择适当的重载:
template <template <typename> class T>
void A {};
template <template <unsigned int> class T>
void B {};
A<Foo> a; // resolves to Foo<T>
B<Foo> b; // resolves to Foo<N>
你认为这样的功能有用吗?是否有一些"好"(即技术)原因说明这在当前C++中是不可能的?
完整指南(亚马逊)中的第 12.5 节包含以下引用:
您可能合理地想知道为什么只有类模板可以部分专用化。原因大多是历史原因。 也许可以为函数模板定义相同的机制(参见第 13 章)。
在某些方面 重载函数模板的效果类似,但也存在一些细微的区别。这些差异是 主要与主模板需要 遇到使用时抬头查找。专业是 仅在之后考虑,以确定应采用哪种实现 使用。
相反,必须引入所有重载的函数模板 通过查找它们进入过载集,它们可能来自 不同的命名空间或类。这增加了 无意中使模板名称有些过载。
相反,它 也可以想象允许类模板的重载形式。 下面是一个示例:
// invalid overloading of class templates template<typename T1, typename T2> class Pair; template<int N1, int N2> class Pair;
但是,似乎并不迫切需要 这样的机制。
此外,C++(亚马逊)的设计与演变在第 15.10.3 节中包含此引用
因此,我的结论是,我们需要一个"专业化"的机制 模板。这可以通过接受一般重载来完成 或通过一些更具体的机制。我选择了特定的机制 因为我认为我主要是在解决由以下原因引起的违规行为 C 语言中的不规则性,并且因为过载的建议总是 引起抗议的嚎叫。我试图保持谨慎和 保守的;我现在认为这是一个错误。专业化为 最初定义的是一种受限和异常形式的重载 这与语言的其余部分不符。
大胆强调我的。我将其解释为函数重载解析比类专业化更难实现(并且由用户正确)。所以可能没有真正的技术障碍(类似于函数模板部分专业化),而是一个历史事故。
您不能"重载"类型参数、非类型参数和模板参数,但您可以专门化可变参数模板:
template <typename... T>
struct Foo;
template <typename T1>
struct Foo<T1> {};
template <typename T1, typename T2>
struct Foo<T1,T2> {};
这已经存在了一段时间,但我在搜索时仍然找到了这篇文章。感谢@log0为我提供了一个良好的开端。这是一个解决方案,可避免需要为所有可能的枚举提供模板专用化。它确实做了一个假设:您可以根据其自身及其基类来定义每个模板扩展。(这将在下面FooImpl
中完成):
template <typename... T>
struct Foo;
template<typename T>
struct Foo<T> { /* implementation of base class goes here*/};
template <typename C, typename Base>
struct FooImpl : public Base { /* implementation of derived class goes here */};
template<typename C, typename... Bases>
struct Foo<C, Bases...> : FooImpl<C, Foo<Bases...> > { /*NO IMPLEMENTATION HERE */};
使用 FooImpl
打破了否则产生的模棱两可的递归。然后,这允许如下声明:
Foo<int> foo_int;
Foo<int, double> foo_int_double;
Foo<int, float, double> foo_int_float_double;
也许这就是STL现在的做法?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 为什么使用SFINAE而不是函数重载
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 为什么在运算符重载时需要参考?
- 为什么常量词在重载运算符中不与 ostream 对象一起使用<<?
- 为什么我可以在不重载 "=" 运算符的情况下将一个对象分配给另一个对象?
- 为什么初始化时没有调用重载赋值运算符?
- 为什么不允许成员函数和非成员函数之间的函数重载?
- 为什么我的运算符 + 重载尽管是通过引用传递的,但仍调用我的复制构造函数?
- 了解运算符重载和迭代器,为什么它会打印出"wrhrwwr"?
- 为什么 std::sort 找不到合适的(静态成员)函数重载?
- C++ 构造函数重载 - 为什么说我需要括号?
- 线性重载:为什么 clang 在 GCC 编译时失败?
- 赋值重载:为什么使用相同的对象会导致程序中出现问题
- 运算符重载 C++ - 为什么我们需要将参数作为 const 和 (...)传递?
- 运算符重载:为什么此代码不起作用
- const和volatile的重载——为什么它可以通过引用工作
- 运算符重载 - 为什么编译器C++不为类提供重载插入器和提取器函数?