Error - Structured binding with TTuple or TPair shows errors in 4.26

My team uses c++17 and we used structured binding with TTuple or TPair.
It was compiled well with the UE4 version 4.25, but after we changed the version to 4.26, it shows errors.

TTuple<int32, int32> Tuple{1,2};
auto[x, y] = Tuple;

In this code block, I get errors in below.

<error-type> x
type "TTuple<int32, int32>" has no components to bind to

and

2>E:/program/Client_New/Source/Client/Private/UI/Compose/Compose_Main.cpp(639): error C3643: 'TTuple<KeyType,ValueType>': cannot decompose type with non-static data-members in both 'UE4Tuple_Private::TTupleBaseElement<KeyType,0,2>' and 'UE4Tuple_Private::TTupleBaseElement<ValueType,1,2>'
2>          with
2>          [
2>              KeyType=int32,
2>              ValueType=int32
2>          ]
2>          and
2>          [
2>              KeyType=int32
2>          ]
2>          and
2>          [
2>              ValueType=int32
2>          ]
2>  C:\UnrealEngineFromLauncher\UE_4.26\Engine\Source\Runtime\Core\Public\Templates/Tuple.h(116): note: see declaration of 'UE4Tuple_Private::TTupleBaseElement<KeyType,0,2>::Key'
2>          with
2>          [
2>              KeyType=int32
2>          ]
2>  C:\UnrealEngineFromLauncher\UE_4.26\Engine\Source\Runtime\Core\Public\Templates/Tuple.h(91): note: see declaration of 'UE4Tuple_Private::TTupleBaseElement<ValueType,1,2>::Value'
2>          with
2>          [
2>              ValueType=int32
2>          ]
2>E:/program/Client_New/Source/Client/Private/UI/Compose/Compose_Main.cpp(639): error C3448: the number of identifiers must match the number of array elements or members in a structured binding declaration

I found that TTuple’s parent class is different between the version 4.25 and 4.26, but I have no idea why it can’t be compiled. It would be grateful if anyone give me some hints.

1 Like

Me too…
I have the same problem

I want to know too

AFAIK, in order to support structured binding for non-std:: types, one has to:

  1. Specialize the following
    1. std::tuple_size
    2. std::tuple_element
  2. Provide
    1. Either a specialization of std::get()
    2. Or a get() function that is in the global namespace
    3. Or a get() method (i.e. part of the class)

In my tests, the following seems to do the trick for TTuple

// Add support for structured binding to TTuple

#include <tuple>        // tuple...
#include <type_traits>  // integral_constant

namespace std
{
    template <typename... Types> struct tuple_size<TTuple<Types...>> : integral_constant<size_t, sizeof...(Types)> {};

    template <size_t Idx, typename... Types> struct tuple_element<Idx, TTuple<Types...>> : tuple_element<Idx, tuple<Types...>> {};

    template <size_t Idx, typename... Types> decltype(auto) get(const TTuple<Types...>&  t) { return(t.template Get<Idx>()); }
    template <size_t Idx, typename... Types> decltype(auto) get(const TTuple<Types...>&& t) { return(t.template Get<Idx>()); }
    template <size_t Idx, typename... Types> decltype(auto) get(      TTuple<Types...>&& t) { return(t.template Get<Idx>()); }
}

// Test support for structured binding in TTuple

#include <cinttypes>  // PRId32... https://en.cppreference.com/w/c/types/integer#Format_macro_constants

{
    TTuple<int32, int32> Tuple{1,2};
    auto [x, y] = Tuple;
    UE_LOG(LogTemp, Warning, TEXT("[x:%"PRId32"] [y:%"PRId32"]"), x, y);  // LogTemp: Warning: [x:1] [y:2]
}

HTH

1 Like

ps: forgot to add the following overload template <size_t Idx, typename... Types> decltype(auto) get( TTuple<Types...>& t) { return(t.template Get<Idx>()); }

Thank you for answering, It works!