問題描述
為什么這段代碼有效:
template<
typename T,
std::enable_if_t<std::is_same<T, int>::value, T>* = nullptr>
void Add(T) {}
template<
typename T,
std::enable_if_t<!std::is_same<T, int>::value, T>* = nullptr>
void Add(T) {}
并且可以正確區分這兩個調用:
and can correctly distinguish between these two calls:
Add(1);
Add(1.0);
而以下代碼如果編譯會導致重新定義 Add() 錯誤?
while the following code if compiled results in the redefinition of Add() error?
template<
typename T,
typename = typename std::enable_if<std::is_same<T, int>::value, T>::type>
void Add(T) {}
template<
typename T,
typename = typename std::enable_if<!std::is_same<T, int>::value, T>::type>
void Add(T) {}
所以如果模板參數是類型的,那么我們重新定義了函數,如果是非類型的,那么一切正常.
So if the template parameter is type, then we have redefinition of the function, if it is non-type, then everything is ok.
推薦答案
SFINAE 是關于替代的.所以讓我們代替!
SFINAE is about substitution. So let us substitute!
template<
typename T,
std::enable_if_t<std::is_same<T, int>::value, T>* = nullptr>
void Add(T) {}
template<
typename T,
std::enable_if_t<!std::is_same<T, int>::value, T>* = nullptr>
void Add(T) {}
變成:
template<
class T=int,
int* = nullptr>
void Add(int) {}
template<
class T=int,
Substitution failure* = nullptr>
void Add(int) {
template<
class T=double,
Substitution failure* = nullptr>
void Add(double) {}
template<
class T=double
double* = nullptr>
void Add(double) {}
刪除我們得到的失敗:
template<
class T=int,
int* = nullptr>
void Add(int) {}
template<
class T=double
double* = nullptr>
void Add(double) {}
現在刪除模板參數值:
template<
class T,
int*>
void Add(T) {}
template<
class T
double*>
void Add(T) {}
這些是不同的模板.
現在搞砸了:
template<
typename T,
typename = typename std::enable_if<std::is_same<T, int>::value, T>::type>
void Add(T) {}
template<
typename T,
typename = typename std::enable_if<!std::is_same<T, int>::value, T>::type>
void Add(T) {}
變成:
template<
typename T=int,
typename =int>
void Add(int) {}
template<
typename int,
typename = Substitution failure >
void Add(int) {}
template<
typename T=double,
typename = Substitution failure >
void Add(double) {}
template<
typename T=double,
typename = double>
void Add(double) {}
刪除失敗:
template<
typename T=int,
typename =int>
void Add(int) {}
template<
typename T=double,
typename = double>
void Add(double) {}
現在模板參數值:
template<
typename T,
typename>
void Add(T) {}
template<
typename T,
typename>
void Add(T) {}
這些是相同的模板簽名.這是不允許的,會產生錯誤.
These are the same template signature. And that is not allowed, error generated.
為什么會有這樣的規定?超出了這個答案的范圍.我只是在演示這兩種情況的不同之處,并斷言標準對它們的處理方式不同.
Why is there such a rule? Beyond the scope of this answer. I'm simply demonstrating how the two cases are different, and asserting that the standard treats them differently.
當您使用上述非類型模板參數時,您更改模板簽名而不僅僅是模板參數值.當您使用上述類型模板參數時,您只需更改模板參數值.
When you use a non-type template parameter like the above, you change the template signature not just the template parameter values. When you use a type template parameter like the above, you only change the template parameter values.
這篇關于SFINAE 在類型和非類型模板參數的情況下工作方式不同的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!