其他分享
首页 > 其他分享> > c – 这部分功能模板是否专业化?

c – 这部分功能模板是否专业化?

作者:互联网

在回答了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似乎删除了编译器方言标志,因此问题似乎已经解决,但我不知道它是如何解决的.

解决方法:

使用@Ben Voigt在其他答案的评论中所说的,我收集了一些相关的标准引用:

§14.5.6.2

A function template can be overloaded with other function templates
and with normal (non-template) functions. A normal function is not
related to a function template (i.e., it is never considered to be a
specialization
), even if it has the same name and type as a
potentially generated function template specialization
.

因此,排除函数模板特化作为你正在做的事情,因为即使两个函数模板重载可能潜在地生成相同的函数,它也不是特化.所以它超载了.

Such specializations are distinct functions and do not violate the one definition rule (3.2).

所以它们是不同的功能,这就是为什么它没有错误.

§14.5.6.2.1

If a function template is overloaded, the use of a function template
specialization* might be ambiguous because template argument deduction
(14.8.2) may associate the function template specialization with more
than one function template declaration.

这是我们已经看到的启动,即in_list(a,b),其中b是initializer_list,似乎与两个函数模板匹配.

(*注意,“函数模板专门化”这里并不意味着专门化一个函数模板,它意味着一个已经用类型实例化的函数模板.所以使用模板< typename T> f();, f< int>()是一个功能模板专业化.)

所以我们使用所谓的重载函数模板的部分排序来解决这个问题:

Partial ordering of overloaded function template declarations is
used in the following contexts to select the function template to which a function
template specialization
refers:

— during overload resolution for a call to a function template specialization (13.3.3);

— when the address of a function template specialization is taken;

— when a placement operator delete that is a function template specialization is selected to match a placement operator new (3.7.4.2, 5.3.4);

— when a friend function declaration (14.5.4), an explicit instantiation (14.7.2) or an explicit specialization (14.7.3) refers to a function template specialization.

好的,这就是部分订购的时候.这就是它的作用:

Partial ordering selects which of two function templates is more
specialized than the other by transforming each template in turn (see
next paragraph) and performing template argument deduction using the
function type. The deduction process determines whether one of the
templates is more specialized than the other. If so, the more
specialized template is the one chosen by the partial ordering
process.

然后你进入了一个漫长而费力的过程,确定哪个模板更专业,如果你愿意,你可以阅读,但它真的很复杂,我可能根本不理解(加上,我没有足够的写下来的时间:)).

标签:c,c11,templates,initializer-list,template-specialization
来源: https://codeday.me/bug/20190729/1573411.html