在类型和非类型模板参数的情况下,SFINAE的工作方式有所不同 [英] SFINAE works differently in cases of type and non-type template parameters

查看:85
本文介绍了在类型和非类型模板参数的情况下,SFINAE的工作方式有所不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码为什么起作用:

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) {}

因此,如果template参数是type,那么我们就重新定义了函数,如果它是非type,则一切正常.

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的工作方式有所不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆