How to return multiple values by reference with TTuple?

I’m trying to return 2 values by reference through a TTuple. Each value is a TArray of a UStruct type. However I get the following error “No suitable conversion from std::decay<…> to <…>” I’m pretty new to C++ so wondering where the std::decay is factoring in (as this works fine using a single return value without the tuple.)

TTuple<TArray<FItemSlot>&, TArray<FItemSlot>&> UInventoryManager::SetArrays()
{
	TArray<FItemSlot>& selectedArray = playerInventory;
	TArray<FItemSlot>& droppedArray = playerInventory;

	if (isSelectedStorage) selectedArray = storage;
	if (isDroppedStorage) droppedArray = storage;

	return MakeTuple(selectedArray, droppedArray);
}

I guess TTuple do not support references (but maybe I’m wrong). Maybe you could try with pointers instead of references ?

Anyway, your code looks suspicious to me: by using references, the lines where you assign the array references to the “storage” value would overwrite completely the “playerinventory”. I am not sure this is the intent. Be careful, references have “value” semantics.

Try with pointers instead.

Thanks for the response, I did try with pointers but (as far as I’m aware) they’re not compatible with UStructs as they’re passed by value.

Yes the example code is not ideal, I ended up replacing with a ternary operator

TArray<FItemSlot>& selectedArray = (!isSelectedStorage) ? playerInventory : storage;

And then I ended up changing the function to return only a single array reference based on a bool.

Haven’t used TTuple but I think you should do something like this:

TTuple<uint32, float> *my_tuple(){
    test = TTuple<uint32, float>(128, 9.999);  // test is init somewhere.
    /*
    current computation.
    */
    return &test;  // Return for other computations.
}

and have you used C++ much?

That function creates a tuple on the stack, presumably puts some things it, and then returns the address of the tuple, which now no longer exists.

Being in ‘stack space’ the address will be perfectly valid, but there is no longer a tuple there…

Looking for UB? Eat your heart out. Probably far more boring in reality as it will likely just insta-crash.

Oh sorry. Yes the test will be destroyed when the function my_tuple life span ends.

if your want this tuple to be valid out of the function, you might initialize it somewhere else. e.g., inside a class. Then you have initialization function. process function, and get function.

I have an example using pointer and address.

    FVector2D *select_point()
    {
        int       idx;
        FIntPoint point_meter;

        if (search_point_distance.IsEmpty())
            return nullptr;
        else {
            idx                 = search_point_distance.CreateConstIterator()->Key;
            point_meter.X       = idx % *w;
            point_meter.Y       = *h - 1 - (idx - point_meter.X) / *w;
            curr_search_point.X = point_meter.X + 0.5;
            curr_search_point.Y = point_meter.Y + 0.5;

            return &curr_search_point;
        }
    }

and the curr_search_point is init under ‘private’:

private:
    const int *w;
    const int *h;

    // Point.
    TMap<int, float> point_distance;  // To dynamically hold current search point.
    FVector2D        curr_search_point;

Or you can do this as well.
Say your tuple will be used in func A and its value is calculated in func B.

// Example.
void A(){
    TTuple<> test;

    B(&test);
}

void B(TTuple *test){
    // Calculate value for test.
    // ...
    
    // Assign value.
}

In this case you don’t need to return as you send the pointer in func B and you can access test’s address use *.

edit the reply to fix