2013-05-22 48 views
3

是否可以使用decltype來投射一個值?使用decltype投射一個值,有可能嗎?

例如,讓我們說,我們有以下模板:

template<typename Container> 
auto findInposition(Container& c,int position)->decltype(*(c.begin())) 
{ 
    if(std::distance(c.begin(),c.begin()+position)<c.size()) 
    return c.at(p); 
    /*else 
    return decltype(*(c.begin())(somevalue);*/ 
} 

這在一個容器中,在一個特定的position返回一個項目的價值。比方說,用戶輸入的位置大於容器的大小,在這種情況下,我想返回一個鑄造值,比如鑄造零點或其他東西。我不知道我的例子是否足夠好,我的主要問題是:是否可以使用decltype來投射一個值,如果是的話,怎麼樣?

+0

你嘗試過嗎? – stijn

+1

是的,但你需要改變類型。截至目前,它是一個非常規的參考。 –

回答

4

一般來說,你可以做到這一點。例如:

int i = 0; 
double d = 3.14; 
i = static_cast<decltype(i)>(d); 

但是,請記住你的函數返回一個參考(因爲decltype(*(c.begin()))計算結果爲引用類型):

std::vector<int> v; 
static_assert(std::is_same<decltype(*v.begin()), int&>::value, "!"); // Won't fire 

什麼是在這種情況下,麻煩的是,該功能必須能夠返回對Container::value_type類型對象的引用,但如果somevalue具有不同的類型,則無法將其引用返回爲Container::value_type&

的道理是一樣的,爲什麼你不能做到以下幾點:

int i = 42; 
float& f = static_cast<float&>(i); 

所以,你需要問自己的第一件事情是你findInposition()功能是否真的應該返回一個參考的元素收集(在這種情況下,你想要做什麼是不可能的,就像上面的例子一樣),或者通過值返回該元素的副本。

如果是這樣的話,你堅持使用decltype,您可以通過std::decay變換decltype輸出:

#include <type_traits> 

template<typename Container> 
auto findInposition(Container& c,int position) -> 
    typename std::decay<decltype(*c.begin())>::type 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
{ 
    if(std::distance(c.begin(),c.begin()+position)<c.size()) 
    return c.at(position); 
    else 
    return static_cast< 
     typename std::decay<decltype(*c.begin())>::type>(somevalue); 
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
} 

但在我看來,以下是更清晰:

template<typename Container> 
auto findInposition(Container& c,int position) -> 
    typename Container::value_type 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
{ 
    if(std::distance(c.begin(),c.begin()+position)<c.size()) 
    return c.at(position); 
    else 
    return static_cast<typename Container::value_type>(somevalue); 
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
} 
+0

很好的解釋。謝謝! –

+0

@AvraamMavridis:很高興幫助:) –

相關問題