2014-11-21 31 views
14

Recently I've discovered 有時能夠將rvalues 暫時轉換爲左值可以是 對我有用。它是否明確地將xvalues轉換爲左值以傳遞給函數?

我一直在使用以下工具:

#include <type_traits> 

template <typename T> 
inline constexpr std::remove_reference_t<T> &lvalue(T &&r) noexcept { 
    return static_cast<std::remove_reference_t<T> &>(r); 
} 

時,你必須使用需要左值作爲 參數的函數這是非常有用的,但你沒有什麼那些特殊 價值得到任何利益改變成。因爲當你有興趣在其他輸出 向量是不相關的給定的具體論證。

例如,這樣的:

std::string get_my_file() { 
    std::ifstream ifs("myfile.txt"); 
    return {std::istreambuf_iterator<char>(ifs), {}}; 
} 

可以改變爲這樣:

std::string get_my_file() { 
    return {std::istreambuf_iterator<char>(lvalue(std::ifstream("myfile.txt"))), 
      {}}; 
} 

這:

std::string temp1 = get_my_shader(); 
const char *temp2 = temp1.c_str(); 
glShaderSource(a, 1, &temp2, nullptr); 

可以改變爲這樣:

glShaderSource(a, 1, &lvalue(get_my_shader().c_str()), nullptr); 

並允許這樣的事情:

void foo(int *x) { 
    std::cout << *x << std::endl; 
} 

foo(&lvalue(5)); 

我想肯定我是否調用未定義的行爲或不以任何的這個,因爲我沒有看到任何,雖然有可能一些鑄造規則,將它變成非法(我忽略)。關於臨時工的生命週期,我沒有看到問題,因爲AFAIK,rvalues live until the end of full-expression和該功能的使用僅限於此。

有一個最近約reinterpret_castxvalues 的標準,這似乎是對話題的變化:

https://stackoverflow.com/a/26793404/1000282

編輯:使用參考倒塌

更好的版本的建議:

template <typename T> 
constexpr T &lvalue(T &&r) noexcept { return r; } 
+0

你沒事。通過將xvalues轉換爲左值可以更容易地搞砸的唯一事情是生命期問題,並且您的例子中沒有危險,因爲在創建它的語句之外臨時文件沒有被引用。 ('reinterpret_cast'-proposal實際上並沒有涉及到你的問題。) – Deduplicator 2014-11-21 02:37:04

+0

@Deduplicator謝謝,我提到了rvalues而不是具體的xvalues,因爲這個問題還包含像'&lvalue(5)'這樣的表達式。順便說一句,工作正常。 – 2014-11-21 02:39:57

+1

順便說一句:爲什麼你使用'std :: remove_reference_t'而不是參考摺疊規則? – Deduplicator 2014-11-21 02:44:14

回答

9

正如你所說,你注意不要讓任何指針或引用臨時對象的範圍。
使用您的lvalue功能(我的名稱爲no_move)可以更輕鬆地打破狹窄無意中。

接下來,讓我們看看xvalues是什麼:過期的對象,但仍然是對象。
這意味着,你可以忽略他們在他們的葬禮之旅(如果你將它們傳遞給一個函數,那麼函數自然會這樣做,除非你要求利用)。

你提到的最後一點是用prvalue調用,這肯定不是一個對象。
但即使這不是問題,因爲在調用函數時,會創建一個臨時對象。
而且臨時自然也會存活到聲明的結尾。

另外,使用std::remove_reference_t<T>&對於返回類型lvalue是不必要的,您可以直接使用T&並依賴引用合攏規則。此外,static_castinline是多餘的。

template <typename T> constexpr T& lvalue(T&& r) noexcept {return r;} 
相關問題