2012-09-12 37 views
2

我想在C++ 11中實現等效的Linux宏ACCESS_ONCEACCESS_ONCE(x)將x的地址轉換爲指向與x相同類型的volatile的指針,然後對其進行解引用。這迫使編譯器不通過這個宏來優化對x的訪問(並且在這裏只發生一次訪問)。C++ access_once

我試圖做到這一點在C++ 11涉及decltype

#define ACCESS_ONCE(x) (*static_cast<decltype(x) volatile *>(&(x))) 

這適用於大多數情況下,我卻用它曾經像這樣:

void foo(void **bar) { 
    while (ACCESS_ONCE(*bar) != NULL) 
    ; 
} 

這失敗的錯誤:

'volatile' qualifiers cannot be applied to 'void*&' 

我在做什麼錯?

+0

這裏正確的轉換是'const_cast',儘管它的名字可以添加和刪除'volatile'限定符以及'const'限定符。 –

+0

@PeteBecker我不同意。 'static_cast'在這裏是正確的選擇。 'const_cast'比必要的更強大。允許'static_cast'添加cv-qualifiers,因爲這個轉換總是安全的。 'const_cast'應該保留用於實際需要不安全轉換的情況,以便刪除* cv-qualifier。 –

+0

@DirkHolsopple - 'static_cast'比必要的更強大,因爲它允許更改類型。 –

回答

5

宏更改爲這樣:

#define ACCESS_ONCE(x) (*static_cast<std::remove_reference<decltype(x)>::type volatile *>(&(x))) 

解引用在參考指針的結果。宏正試圖將它投射到void *& volatile而不是像你想要的void * volatile。您不能將volatile限定符應用於引用類型,因此您必須使用std :: remove_reference將其更改爲正常的非引用類型。

+0

非常感謝。這解決了這個問題,並教會了我一些C++ 11技巧。 – dschatz

+0

避免宏 - 它們用於C黑客 – Walter

7
template<typename T> 
inline T volatile &access_once(T &t) { 
    return static_cast<T volatile &>(t); 
} 

這避免了宏,是簡單,因爲類型推導和參考去除模板簽名隱含的而且避免了冗餘的地址和尊重運營商(引用類型之間的靜態鑄造定義爲做同樣的事情作爲地址,轉換,然後解除引用)。它只是表現性的,我不認爲它取決於C++ 11中的任何東西。

+0

它是否適用於已經存在易失性的對象(您想要的易失性如何)?我建議在return語句和返回類型上使用T中的remove_volatile。 – Tomek

+1

它實際上對易失性對象起作用。冗餘volatile是合法的,不會導致任何問題。 – bames53