这是与OP的Is constexpr useful for overload解决方案相关的问题。
基本上,他用过
template<class T>
typename std::enable_if<std::is_arithmetic<T>::value, int>::type
f(T&& n) { ... }
和
template<class T>
typename std::enable_if<!std::is_arithmetic<T>::value, int>::type
f(T&& n) { ... }
知道是否已调用f()
是一个编译时变量(例如文字:f(42)
)或左值(例如局部变量:f(argc)
)作为其参数。< / p>
问:这是如何工作的? (我预计,在两次调用中,都会调用第一个重载(即std::is_arithmetic<T>::value == true
)
以下是一个完整的例子:
#include <iostream>
#include <type_traits>
using std::cout;
using std::endl;
template<class T>
constexpr
typename std::enable_if<std::is_arithmetic<T>::value,
int>::type
inline f(T&& n)
{
//cout << "compile time" << endl;
return 1;
}
template<class T>
typename std::enable_if<!std::is_arithmetic<T>::value,
int>::type
inline f(T&& n)
{
//cout << "run time" << endl;
return 0;
}
int main(int argc, char* argv[])
{
const int rt = f(argc);
constexpr int ct = f(42);
cout << "rt: " << rt << endl;
cout << "ct: " << ct << endl;
}
答案 0 :(得分:1)
表格
的模板功能template <typename T>
void func(T&& t);
看起来像,好像它需要一个r值引用。但实际上T&&
这里是Scott Meyers所谓的通用引用,也称为转发引用。根据参数的值类别,可能会发生不同的事情。让我们来看看每个案例:
t是非常数左值,例如
int i = 0;
func(i);
在这种情况下,T被推断为int
的左值引用,即T=int&
。
t是一个const值,例如
const int i = 1;
func(i);
同样,在这种情况下,T
推断为const int&
。
t是一个右值,例如
func(1);
在这种情况下,T
被推断为int
正如我们预期的那样
究竟为什么这些推论以这种方式发生,与参考折叠的规则有关;我强烈推荐阅读Scott Meyers&#39;如果您有兴趣,请参阅有关该主题的文章。
上面的最后一个案例也说明了在C和C ++中,文字(字符串文字除外)总是rvalues。
这与enable_if
有什么关系?如果您使用整数文字调用f
,那么T
推断为普通int
。显然,is_arithmetic<int>
是正确的,所以第二个函数得到SFINAE并且第一个被调用。第一个被调用。
然而,当使用左值调用时,T
被推断为(const) int&
。引用是 not 算术,因此第一个函数消失,只留下第二个函数被调用。