2014-01-26 47 views
30

我看到在宏內使用decltype(x)其中x是一個變量名稱,因爲對象的類型在宏內部是未知的。什麼時候應該使用decltype(x)而不是auto來聲明變量的類型?

例如:

decltype(x) y = expr; 

我可以很容易地使用auto代替decltype。那麼decltype需要變量類型聲明而不是auto

+1

'decltype(X)Y = EXPR;'是不一樣的'自動Y = EXPR;' - 可能有很大可能是某種形式的在前者的隱式轉換,但不是在後者。 – Flexo

+0

'auto'適合普通人和日常使用。 'decltype'用於通常的庫代碼,在正常生活中你應該幾乎看不到它。 –

+0

** <評論刪除> **評論不適合長時間討論問題的主題。如果你想進一步討論這個問題是否在話題上,請訪問[Meta Stack Overflow](http://meta.stackoverflow.com)。 – animuson

回答

17

應該使用它時所需的y類型是:

  • expr類型不同(或可能不同)。如果它是相同的,那麼auto會更簡潔。
  • 類似地對於auto &expr類型的其他修改auto可以表示。

和下列之一:

  • 依賴於周圍的代碼的東西(即,不總是相同的類型),並難以使用型性狀或類似來寫。這將傾向於在模板代碼中發生。可能有一種類型特徵可用於從模板參數中獲取所需的類型,但是可能不會如此使用decltype可以幫助您定義一個特徵。
  • 總是相同的類型,(或依賴於模板參數的方式,使用現有的類型特徵或類似的方式很容易表達),但類型是非常冗長的寫和有一個更短,更清晰的表達式,你可以改爲使用。

因此,例如更換std::iterator_traits<RandomAccessIterator>::value_typedecltype(*it)很可能是一場勝利,雖然auto不經常處理這樣的情況。主觀判斷進入「什麼是困難」,「什麼是囉嗦」和「什麼是明確的」,但是無論在特定情況下如何做出這些判斷,程序規則都可以是相同的。

+1

但是在''decltype(x)y = expr;''這裏''y''和''expr''不是同一類型的情況下,寫''auto y = x (表達式);''?或者這是否僅僅反映個人偏好,以及是否希望進行明確的轉換? –

+0

@ DiederickC.Niehorster:如果'x'是類型,那麼你只需寫'x y = expr;'(或'x y {expr};'),而不是這兩者中的任何一個。我認爲這個問題假定'x'不是一種類型。如果'x'不是一個類型,那麼'x(expr)'可能不起作用。如果它是一個類型,它是一個「可怕的」C風格的演員,它可能會做'const_cast'或'reinterpret_cast'或者兩者都取決於'x'類型的結束。更好地使用'static_cast'。 –

7

只要您的變量類型與正在評估的表達式無關。

E.g:

struct Bar 
{ 
    Bar(int) {} // implicitly constructable 
} 

struct Bar2 
{ 
    Bar2(int) {} // implicitly constructable 
} 

struct Foo 
{ 
    static Bar var; 
} 

struct Foo2 
{ 
    static Bar2 var; 
} 

template <typename T> 
void dummy() 
{ 
    decltype(T::var) myVar = 42; 
} 

dummy<Foo>(); // myVar is of type Bar1 
dummy<Foo2>(); // myVar is of type Bar2 
auto myAutoVar = 42; // type is int 

當然,這只是一個使用情況下,有更多的在那裏。

16

當你想y總是有任何聲明的類型x是。

+0

但是我仍然會知道'x'的類型,所以我可以用'[typeOfX] y = expr'替換'decltype(x)'。 –

+7

這使得'y'始終具有該特定類型。不一樣。 –

+3

@templateboy你總是知道'foo(a + b/c)'的返回類型嗎? – Flexo

6

decltype是顯着更多才多藝,auto,可以始終用它來代替它。因此,我認爲decltype只能在完全必要的情況下才能使用,所以如果auto產生錯誤的結果,應該使用decltype。此外,您還不能使用auto作爲回報類型和參數,因此您也可以在此處使用decltype。 C++ 14將顯着增加auto的潛在用途,我想C++ 17會走得更遠。所以情況下使用decltype將只有當你需要更改所得到的expr

另一個要考慮的類型是decltype是不是真的有必要,除非你正在編寫庫代碼,汽車是日常編程如果不錯你想讓你的代碼更加簡潔,但是儘可能使用盡可能多的auto是有好處的,但在使用類似lambda表達式的類型時,這是非常必要的。

16

decltype當你需要返回一些未知類型,這是在編譯期間評估變得得心應手:

template<class A, class B> 
void MultiplyAB(A a, B b, decltype(a*b)& output) 
{ 
    output = a * b; 
} 

此外,如果你不喜歡的輸出由參考處理的方式,那麼你就可以還使用後期指定的返回類型(和也使用decltype):

template<class A, class B> 
auto MultiplyAB(A a, B b) -> decltype(a*b) 
{ 
    return a * b; 
} 

所有這一切,更多的,由B. Stroustrup的在C++ FAQ說明。

+0

TBH後者沒有定義變量的類型,它定義了返回類型。 – MSalters

4

在你的問題的情況下,

  • 當你想與正是由於原始變量相同類型一個新的變量,您應該使用decltype

  • 當你想分配一些表達式的值到一個新的變量,你想要或需要的類型推斷應該使用auto

decltype(x) y總是宣稱y與嚴格的相同類型的x與聲明的類型。特別是:

  • 如果x的類型爲const int然後y將有類型const int
  • 如果x具有類型int[100]那麼y將具有類型int[100]
  • 如果x具有類型int f(int)y將具有類型int f(int)。是的,這實際上聲明瞭另一個函數與原始類型相同。
  • 如果x有類型int&然後y將有類型int&;並且如果x具有類型int&&,則y將具有類型int&&

auto y = x將宣佈y有以下類型,當x有以下幾種類型:

  • 如果x有類型const int,然後y將有類型int。即,auto剝離頂級cv限定符。
  • 如果x具有類型int[100],則y將具有類型int*。也就是,auto執行數組到指針轉換。 [1]
  • 如果x具有類型int f(int),那麼y將具有類型int (*)(int)。也就是說,auto執行的功能爲一個函數指針轉換。 [2]
  • 最後,如果x具有類型int&int&&,則y將具有類型int。即,auto刪除引用

[1]此處不能使用decltype,因爲您無法複製初始化數組。

[2],則不能使用decltype這裏,因爲你無法初始化函數。

[3]之所以auto條的引用是,C++沒有引用類型的表達式!一旦初始化,參考的「參考性」就變得不可見。

注意decltype也做完全不同的事情,當它的參數不是ID表達,我不會進入這裏。

+0

我認爲如果'x'被聲明爲'int &&'它仍然是一個左值,只是它被允許綁定到右值。 – ymett

+0

啊,你說得對。 – Brian

相關問題