繁体   English   中英

模板参数推导如何区分左值和文字/编译时值

[英]How does template argument deduction distinguish between an lvalue and a literal/compile-time value

这是与OP的constexpr对重载有用的解决方案有关的问题。

基本上,他用

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) )作为其参数。

问:如何运作? (我希望在两个调用中都将调用第一个重载(即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;
}

表单的模板功能

template <typename T>
void func(T&& t);

看起来好像需要一个r值参考。 但是实际上, T&&这就是Scott Meyers所谓的通用引用 ,也称为转发引用。 根据参数的值类别,可能发生不同的事情。 让我们看一下每种情况:

  1. t是非常量左值,例如

     int i = 0; func(i); 

    在这种情况下,T被推导为int的左值引用,即T=int&

  2. t是一个常量左值,例如

     const int i = 1; func(i); 

    类似地,在这种情况下, T被推导为const int&

  3. t是一个右值,例如

     func(1); 

    在这种情况下,正如我们可能预期的那样,推导Tint

这些推论之所以如此发生,恰恰与参考折叠的规则有关。 如果您有兴趣,我强烈建议阅读Scott Meyers关于该主题的文章。

上面的最后一种情况还说明了一点,在C和C ++中,文字(字符串文字除外)始终是右值。

这与enable_if什么关系? 好吧,如果您的f用整数字面量调用,则T被推导为纯int 显然, is_arithmetic<int>为true,因此第二个函数被SFINAE退出,第一个函数被调用。

但是,当用左值调用时, T推导为(const) int& 引用不是算术运算,因此第一个函数消失了,仅剩下第二个函数要调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM