阅读this question让我想知道:是否存在禁止类模板重载的技术原因?
通过重载,我的意思是有几个模板具有相同的名称,但参数不同,例如
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 ++中这是不可能的?
答案 0 :(得分:33)
模板完整指南(Amazon)中的第12.5节包含此引用:
您可能会合理地想知道为什么只有类模板可以部分专业化。原因主要是历史原因。 可能可以为函数模板定义相同的机制(参见第13章)。
在某些方面 重载函数模板的效果类似,但也有一些细微的差别。这些差异是 主要与主要模板需要的事实有关 遇到使用时查找。专业是 之后才考虑,确定应该采用哪种实施方式 用过的。
相反,必须带来所有重载的功能模板 通过查找它们来设置过载,它们可能来自 不同的命名空间或类。这增加了可能性 在某种程度上无意中重载了模板名称。
相反,它 也可以想象允许一种形式的类模板重载。 这是一个例子:
// invalid overloading of class templates template<typename T1, typename T2> class Pair; template<int N1, int N2> class Pair;
然而,似乎并不迫切需要 这样的机制。
此外, C ++的设计和演变(Amazon)在第15.10.3节中包含此引用
因此,我得出结论,我们需要一种“专业化”的机制 模板。这可以通过接受一般的重载来完成 或者通过一些更具体的机制。我选择了一种特定的机制 因为我以为我主要是解决由此造成的违规行为 C中的不规则性以及因为超载的建议总是存在的 制造了抗议的嚎叫。我试图保持谨慎 保守; 我现在认为这是一个错误。专业化 最初定义的是一种限制和异常形式的重载 与其他语言不符合。
大胆强调我的。我认为这说明函数重载解析比类特化更难实现(并且由用户使用)。所以可能没有真正的技术障碍(类似于功能模板部分专业化),而是历史性事故。
答案 1 :(得分:19)
您不能“重载”类型参数,非类型参数和模板模板参数,但您可以专门使用可变参数模板:
template <typename... T>
struct Foo;
template <typename T1>
struct Foo<T1> {};
template <typename T1, typename T2>
struct Foo<T1,T2> {};
答案 2 :(得分:1)
这已经存在了一段时间了,但我在搜索时仍然发现了这篇文章。感谢@ log0为我提供了良好的开端。这是一个避免需要为所有可能的枚举提供模板特化的解决方案。它确实做了一个假设:您可以根据自身及其基类定义每个模板扩展。 (这将在下面的Reindex
中完成):
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
也许这就是STL现在如何做到的?