Reputation: 61
Given this prototype which does a Endian conversion:
time_t Flip( time_t );
I would like to use the return value in a function that takes a BYTE* as an argument. Something like this:
SetBytesAt( 0, (BYTE*)&(Flip( t )) );
But this does not compile. Gives me this error "& requires l-value". If the () are removed from around the Flip function, the same error is generated.
Now, I know that I can just do this:
time_t temp_t = Flip( t );
SetBytesAt( 0, (BYTE*)&temp_t );
But it seems to me that I should be able to accomplish the same thing without the temporary temp_t variable.
Upvotes: 6
Views: 7927
Reputation: 272657
Unfortunately, no. You cannot take the address of a temporary (more correctly, an r-value). That's just the way the language has been defined.
Upvotes: 12
Reputation: 145359
It's no big deal to do what you want, but it's unclean.
Here goes:
template< class Type >
Type const& ref( Type const& v ) { return v; }
int main()
{
time_t t = blah blah;
SetBytesAt( 0, const_cast<Byte*>( reinterpret_cast<Byte const*>( &ref( Flip( t ) ) ) ) );
}
Technically this can work if SetBytesAt
copies the bytes, but if SetBytesAt
stores the pointer, and that pointer is later used, then it's undefined behavior.
Anyway, don't do that.
Now I'll list what's wrong with the original concept:
Discarding type knowledge by using typeless pointer argument.
→ Means a lot of extra work because the type is not known.
Discarding const knowledge by using pointer to non-const argument.
→ Means a lot of extra work because the constness is not known.
Flipping byte order of data = ungood except in low level network code.
→ Means a lot of extra work because the byte order is not known.
So, again, don't do that.
Instead, do the opposite: preserve type information, preserve constness information, and don't mess with the raw bytes.
Upvotes: 0
Reputation: 8180
Actually, it became possible in C++11. There, r-value references were introduced. However, I don't know, which compiler does it already.
Upvotes: 1
Reputation: 355177
Don't try this at home.
template <typename T>
class AddressableTemporary
{
public:
AddressableTemporary(T const value)
: value_(value)
{
}
operator T*() { return &value_; }
private:
T value_;
};
template <typename T>
AddressableTemporary<T> MakeAddressable(T value)
{
return AddressableTemporary<T>(value);
}
Used as:
int F() { return 42; }
void G(int const* const p) { std::cout << *p; }
int main()
{
G(MakeAddressable(F()));
}
But really, don't do this. Either use a variable, or write a wrapper function that encapsulates usage of the variable, or rework your code so that you don't need to worry about this (e.g., modify the function so that it takes, say, a const reference).
Upvotes: 3
Reputation: 258618
You can't, for the exact reason given by the error message - & requires l-value
.
The call Flip(t)
is not an l-value, so it's impossible.
Upvotes: 0
Reputation: 9587
To the best of my knowledge, that is not possible in C++.
Ask yourself this: how will you access the modified result after SetBytesAt
returns?
Return values are normally copied (or moved) to an actual variable in the caller function. The temporary space reserved for the returned value is no longer available after the function returns. Theoretically, you would be stack memory that is no longer valid. This mistake happens in practice when returning references to local variables.
Upvotes: 1
Reputation: 27233
You need to use a temporary variable. You can only take address of l-values. There is no way to take address of a return value.
On some platforms, return value is only stored in a register and hence doesn't even have an address. You need to store it in memory before you can pass its address to another function.
Upvotes: 1