我在回答this question
之后想出了这个我有一个简单的函数模板(C ++ 11):
template<class elem_t, class list_t>
bool in_list(const elem_t& elem, const list_t& list) {
for (const auto& i : list) {
if (elem == i) {
return true;
}
}
return false;
}
但是GCC发出了警告,因为它似乎不喜欢将模板参数推断为std :: initializer_list。所以,不假思索地,我做了一个专业化:
template<class elem_t>
bool in_list(const elem_t& elem, std::initializer_list<elem_t> list) {
for (const auto& i : list) {
if (elem == i) {
return true;
}
}
return false;
}
这很有用。没有更多的警告。但当我再看一遍并考虑它时,我记得C ++不支持对函数模板进行部分模板特化。但这就是看起来的样子。我唯一的猜测是这是允许的,因为std :: initializer_list仍然依赖于模板参数,所以它本质上是一个不同的模板。但是我不确定它是不是应该是这样的(是不是有一些关于模板没有重载?)。
接受这个是标准行为吗?为什么?
作为奖励问题,为什么GCC不喜欢将模板参数推断为std :: initializer_list?期望我复制并粘贴代码并用std :: initializer_list替换参数似乎很愚蠢。
警告信息:
test.cpp: In function ‘int main()’:
test.cpp:33:43: warning: deducing ‘const list_t’ as ‘const std::initializer_list<int>’ [enabled by default]
test.cpp:6:6: warning: in call to ‘bool in_list(const elem_t&, const list_t&) [with elem_t = int, list_t = std::initializer_list<int>]’ [enabled by default]
test.cpp:33:43: warning: (you can disable this with -fno-deduce-init-list) [enabled by default]
被in_list(3, {1, 2, 3, 4, 5});
编辑:显然,根据我的GCC版本(cite)的工作草案,将模板参数推断为initializer_list是一个扩展名。所以新问题:这仍然是最终c ++ 11标准的延伸吗?如果是这样,这意味着我需要为符合标准的代码添加第二个函数。感谢你的帮助!
EDIT2:GCC 4.7似乎删除了编译器方言标志,因此问题似乎已经解决,但我不知道 是如何解决的。
答案 0 :(得分:4)
使用@Ben Voigt在其他答案的评论中所说的,我收集了一些相关的标准引用:
§14.5.6.2
功能模板可以与其他功能模板重载 并具有普通(非模板)功能。正常功能不是 与功能模板相关(即,从未被认为是a 专业化),即使它具有相同的名称和类型 可能生成的函数模板专业化。
因此,排除函数模板特化作为你正在做的事情,因为即使两个函数模板重载可能潜在地生成相同的函数,它也不是特化。所以它正在超载。
此类专业化是不同的功能,不违反一个定义规则(3.2)。
所以它们是不同的功能,这就是它没有错误的原因。
§14.5.6.2.1
如果函数模板被重载,则使用函数模板 由于模板参数推导,特殊化*可能不明确 (14.8.2)可以将功能模板专业化与更多相关联 比一个函数模板声明。
这是我们已经看过的内容,in_list(a, b)
其中b
initializer_list
似乎与两个功能模板匹配。
(*注意,“函数模板专门化”这里并不意味着专门化一个函数模板,它意味着一个已经用类型实例化的函数模板。因此template<typename T> f();
,f<int>()
是一个功能模板专业化。)
所以我们使用所谓的重载函数模板的部分排序来解决这个问题:
重载函数模板声明的部分排序是 在以下上下文中用于选择函数的函数模板 模板专业化 是指:
- 在重载解析期间调用函数模板特化(13.3.3);
- 当采用功能模板专业化的地址时;
- 选择作为功能模板专门化的展示位置运算符时,选择匹配展示位置运算符new(3.7.4.2,5.3.4);
- 当友元函数声明(14.5.4),显式实例化(14.7.2)或显式特化(14.7.3)引用函数模板特化时。
好的,这就是部分订购的时候。这就是它的作用:
部分排序选择两个功能模板中的哪一个更多 通过依次转换每个模板来实现专业化(参见 下一段)并使用。执行模板参数推导 功能类型。扣除过程确定是否其中之一 模板比另一个更专业。如果是这样,就越多 专用模板是由部分排序选择的模板 过程
然后你进入了一个漫长而费力的过程,确定哪个模板更专业,如果你愿意,你可以阅读,但它真的很复杂,我可能根本不理解(加上,我不知道)有足够的时间来写它:))。
答案 1 :(得分:3)
这不是部分专业化。你正在做的是重载功能。