2012-11-02 41 views
39

(如果你是一個C++ 11的親,請跳到大膽的段落。)刪除引用(返回的T而不是T&其中T&是decltype)

比方說,我想寫一個模板它調用和返回傳遞的對象哪種類型的結果的方法是模板參數:

template<ReturnType, T> 
ReturnType doSomething(const T & foo) { 
    return foo.bar(); // EDIT: Might also be an expression introducing a temp val 
} 

所以T必須有一個方法ReturnType T::bar() const爲了在這樣的調用中使用:

struct MyClass { 
    ... 
    int bar() const; 
    ... 
}; 
... 
MyClass object; 
int x = doSomething<int, MyClass>(object); 

我們沒有寫MyClass感謝類型推演和呼叫變爲:

int x = doSomething<int>(object); 

但省略<int>編譯錯誤太多的結果,因爲該方法不需要在順序返回INT被分配到之後的x(例如,它可能會返回char)。

在的C++ 0x/11我們有autodecltype,使我們可以用它來推斷一個模板方法的返回類型:

template<T> 
auto doSomething(const T & foo) -> decltype(foo.bar()) { 
    return foo.bar(); // EDIT: Might also be an expression introducing a temp val 
} 

編譯器現在將找出的foo.bar()類型並且只是將其用作返回類型。隨着我們的具體類MyClass這將是一個int及以下就足夠了:

int x = doSomething(object); 

現在我的問題:

如果MyClass的bar()定義爲返回一個int&doSomething(object)返回類型也將是int& = decltype(foo.bar())。這是一個問題,因爲現在G ++符合我的返回引用臨時

我該如何解決這個問題?有沒有像remove_reference那樣可以像remove_reference(decltype(foo.bar()))一樣使用?

我想到了剛剛宣佈一個輔助方法,這需要T&並返回T,然後定義的doSomething返回類型爲decltype(helper(foo.bar()))。但是必須有更好的方式,我感覺它。

+3

這是一個問題?你所要做的就是傳遞參考文獻。是的,有'std :: remove_reference :: type'。 – GManNickG

+0

@GManNickG我不想在我的程序中發出警告。我想用'-Werror -Wall'進行編譯。感謝'std :: remove_reference'提示,我知道我以前看過這個,但在搜索「C++ 11模板類型扣除刪除參考」時無法在google上找到它,也許我的搜索過於局部化了:) – leemes

+0

不,我說的不應該有任何警告。如果'foo.bar()'返回一個引用,那麼你應該能夠很好地作爲引用返回。 – GManNickG

回答

44

要刪除一個參考:

#include <type_traits> 

static_assert(std::is_same<int, std::remove_reference<int&>::type>::value, "wat"); 

你的情況:

template <typename T> 
auto doSomething(const T& foo) 
    -> typename std::remove_reference<decltype(foo.bar())>::type 
{ 
    return foo.bar(); 
} 

只是要清楚,注意書面返回參考就好了:

#include <type_traits> 

struct f 
{ 
    int& bar() const 
    { 
     static int i = 0; 
     return i; 
    } 
}; 

template <typename T> 
auto doSomething(const T& foo) 
    -> decltype(foo.bar()) 
{ 
    return foo.bar(); 
} 

int main() 
{ 
    f x; 
    return doSomething(x); 
} 

返回的參考可以簡單地傳遞,沒有錯誤。你在評論中的例子是它變得重要和有用的地方:

template <typename T> 
auto doSomething(const T& foo) 
    -> decltype(foo.bar()) 
{ 
    return foo.bar() + 1; // oops 
} 
+0

謝謝,這個作品很有魅力。 :) – leemes

+3

在C++ 14中,您也可以使用'std :: remove_reference_t '。 – Kupiakos

+1

@ Kupiakos在C++ 14中,你可以使用自動返回類型而不需要結尾的decltype。 –

相關問題