Reputation: 1218
I'm trying to implement the equivalent of the Linux macro ACCESS_ONCE
in c++11.
ACCESS_ONCE(x)
takes the address of x, casts to a pointer to a volatile of the same type as x, then dereferences it. This forces the compiler to not optimize out accesses to x through this macro (and make the access occur only once here).
My attempt to do it in c++11 involves decltype
:
#define ACCESS_ONCE(x) (*static_cast<decltype(x) volatile *>(&(x)))
This works for most cases but I use it once like so:
void foo(void **bar) {
while (ACCESS_ONCE(*bar) != NULL)
;
}
This fails with an error:
'volatile' qualifiers cannot be applied to 'void*&'
What am I doing wrong?
Upvotes: 2
Views: 676
Reputation: 88155
template<typename T>
inline T volatile &access_once(T &t) {
return static_cast<T volatile &>(t);
}
This avoids macros, is simpler because the type deduction and reference removal is implicit in the template signature and it avoids the redundant address-of and deference operators (static casting between reference types is defined to do the same things as taking the address, casting and then dereferencing). It's just as performant and I don't think it depends on anything in C++11.
Upvotes: 7
Reputation: 8831
Change the macro to this:
#define ACCESS_ONCE(x) (*static_cast<std::remove_reference<decltype(x)>::type volatile *>(&(x)))
Dereferencing a pointer results in a reference. The macro is trying to cast it to a void *& volatile
instead of a void * volatile
like you want. You can't apply the volatile qualifier to a reference type so you have to use std::remove_reference to change it to the normal non-reference type.
Upvotes: 5