簡體   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