[英]C++ Template specialization by type of non-type parameter
根據非類型成員的類型,相同模板函數的變體是否有效?
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);
鏗鏘聲和gcc聲音沉默,但MSVC報道
warning C4305: 'specialization': truncation from 'int' to 'bool'
我想避免要求指定常量類型:
f<sometype, bool, true>
並希望確保常量值和目標值匹配。
---- 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;
}
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
到bool
正在縮小,除非該值是值0
或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
overload,那么g ++會默默地接受無效代碼而不進行診斷。
在您的代碼中有一個非const左值引用參數:
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>
情況下修剪它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.