c++ - 非类型参数类型的 C++ 模板特化
问题描述
具有因非类型成员的类型而不同的相同模板函数的变体是否有效?
template<typename T, unsigned int V>
void f(unsigned int& v) { v = V; }
template<typename T, bool B>
void f(bool& b) { b = B; }
目的是能够调用
unsigned int meaningOfLife;
f<sometype, 42>(meaningOfLife);
bool areYouAlive;
f<sometype, true>(areYouAlive);
clang 和 gcc 保持沉默,但 MSVC 报告
warning C4305: 'specialization': truncation from 'int' to 'bool'
我想避免要求指定常量类型:
f<sometype, bool, true>
并希望确保常量值和目标值匹配。
---- 麦克维 ----
#include <iostream>
template<unsigned int V>
void f(unsigned int& v) { v = V; }
template<bool B>
void f(bool& b) { b = B; }
int main()
{
unsigned int u { 0 };
bool b { false };
f<42>(u);
f<true>(b);
std::cout << u << b;
}
Rextester 示例:http ://rextester.com/VIGNP16100
Warning(s):
source_file.cpp(14): warning C4305: 'specialization': truncation from 'int' to 'bool'
/LIBPATH:C:\boost_1_60_0\stage\lib
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x64
421
解决方案
简短回答:代码正常,MSVC 发出虚假警告。
MSVC 和 g++ 在非类型模板参数匹配中都有错误,但它们确实为您的特定示例选择了正确的错误。
长答案:具有非类型模板参数的重载函数模板是可以的。
然而,模板参数与模板声明的匹配并不像预期的那样工作(无论如何我都是这样)。所有匹配的模板都被输入到重载决议中。在任何阶段,它都不喜欢“精确匹配”。
根据 C++17 [temp.arg.nontype/]2,允许转换的常量表达式。这意味着,例如:
42
匹配int
和unsigned int
.42u
匹配int
和unsigned int
.1u
匹配unsigned int
,int
和bool
.
请注意,转换后的常量表达式不能包含缩小转换,并且int
tobool
正在缩小,除非该值是 value0
或的常量表达式1
。所以42
不匹配bool
。(参考:C++17 [expr.const]/4)。
如果我们有以下设置:
template<unsigned int V> void g() {}
template<bool B> void g() {}
那么正确的行为是:
g<42>()
来电g<unsigned int>
。g<1>()
是模棱两可的。g<1u>()
是模棱两可的。
MSVC 2017 和 g++ 7,8 都错误地允许g<42>
匹配g<bool>
,并报告g<42>
为模棱两可。
MSVC 发出您在生成无效匹配时看到的警告;g++ 根本没有给出诊断。如果我们移除unsigned int
重载,那么 g++ 会静默接受无效代码而无需诊断。
在您的代码中有一个非常量左值引用参数:
template<unsigned int V> void h(unsigned int&) {}
template<bool B> void h(bool&) {}
这会有所不同,因为重载解析可以根据函数参数进行选择。对于通话:
unsigned int m;
h<1u>(m);
然后两个重载h
都进入重载决议,但是然后h<unsigned int>
获胜,因为h<bool>(m)
这将是无效的。
如上所述,呼叫h<42>(m);
在第一阶段获胜,因为这无法匹配h<bool>
;但在 MSVC++(和 g++)中,它错误地允许h<bool>
在这个阶段通过,但稍后会根据h<1u>
情况对其进行修剪。
推荐阅读
- session-variables - 如何从昨天的高点和收盘点画水平线?以及如何解决时间格式?行间填充
- python - 如何在Python中获取匹配名称的列表文件
- ruby-on-rails - 在 Heroku 上部署 Rails 应用程序时 Webpack 未找到错误
- java - 线程调度策略、上下文切换时间和线程的总 CPU 时间存在问题。Linux
- ruby-on-rails - 未定义的方法“变形虫”rails 5.2
- javascript - 存储在火库中并将 url 保存在变量中
- angular - ngx-material-timepicker v5.4.3 - 修改timepicker-field的样式
- 3d - x3dom 中的叠加透明表面呈现锯齿状、斑驳状的外观
- azure-cognitive-search - 短语搜索运算符的 Azure 认知搜索命中亮点
- c# - 在 xmlnode 中选择子节点