user1296467
user1296467

Reputation: 61

How to get the address of the return value of a function in C++

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

Answers (7)

Oliver Charlesworth
Oliver Charlesworth

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

Cheers and hth. - Alf
Cheers and hth. - Alf

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

Matthias
Matthias

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

James McNellis
James McNellis

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

Luchian Grigore
Luchian Grigore

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

Irfy
Irfy

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

Adam Zalcman
Adam Zalcman

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

Related Questions