kfs*_*one 4 c++ templates language-lawyer visual-c++-2017
根据非类型成员的类型,相同模板函数的变体是否有效?
template<typename T, unsigned int V>
void f(unsigned int& v) { v = V; }
template<typename T, bool B>
void f(bool& b) { b = B; }
Run Code Online (Sandbox Code Playgroud)
目的是让人能够打电话
unsigned int meaningOfLife;
f<sometype, 42>(meaningOfLife);
bool areYouAlive;
f<sometype, true>(areYouAlive);
Run Code Online (Sandbox Code Playgroud)
铿锵声和gcc声音沉默,但MSVC报道
warning C4305: 'specialization': truncation from 'int' to 'bool'
Run Code Online (Sandbox Code Playgroud)
我想避免要求指定常量类型:
f<sometype, bool, true>
Run Code Online (Sandbox Code Playgroud)
并希望确保常量值和目标值匹配.
---- mcve ----
#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;
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
简答:代码没问题,MSVC发出虚假警告.
MSVC和g ++都有非类型模板参数匹配中的错误,但它们确实为您的特定示例选择了正确的错误.
长答案:使用非类型模板参数重载功能模板是可以的.
但是,模板参数与模板声明的匹配并不像预期的那样(无论如何).所有匹配的模板都输入到重载决策中.在任何阶段,它都不喜欢"完全匹配".
根据C++ 17 [temp.arg.nontype /] 2,允许转换的常量表达式.这意味着,例如:
42比赛int和unsigned int.42u比赛int和unsigned int.1u比赛unsigned int,int和bool.请注意,转换后的常量表达式不能包含缩小转换,并且int要bool缩小,除非该值是值0或的常量表达式1.所以42不匹配bool.(参考:C++ 17 [expr.const]/4).
如果我们有以下设置:
template<unsigned int V> void g() {}
template<bool B> void g() {}
Run Code Online (Sandbox Code Playgroud)
然后正确的行为是:
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 ++默默地接受无效代码而没有诊断.
在您的代码中有一个非const左值引用参数:
template<unsigned int V> void h(unsigned int&) {}
template<bool B> void h(bool&) {}
Run Code Online (Sandbox Code Playgroud)
这有所不同,因为重载决策可以根据函数参数进行选择.致电:
unsigned int m;
h<1u>(m);
Run Code Online (Sandbox Code Playgroud)
然后两个重载h进入重载解析,然后h<unsigned int>获胜因为h<bool>(m)无效.
如上所述,呼叫h<42>(m);在第一阶段获胜,因为这不匹配h<bool>; 但是在MSVC++(和g ++)中,它错误地允许h<bool>在这个阶段进行,但是在h<1u>案件的后期修剪它.
| 归档时间: |
|
| 查看次数: |
288 次 |
| 最近记录: |