Make custom type “tie-able” (compatible with std::tie)

Why the current attempts fail

std::tie(a, b) produces a std::tuple<int&, string&>.
This type is not related to std::tuple<int, string> etc.

std::tuple<T...>s have several assignment-operators:

  • A default assignment-operator, that takes a std::tuple<T...>
  • A tuple-converting assignment-operator template with a type parameter pack U..., that takes a std::tuple<U...>
  • A pair-converting assignment-operator template with two type parameters U1, U2, that takes a std::pair<U1, U2>

For those three versions exist copy- and move-variants; add either a const& or a && to the types they take.

The assignment-operator templates have to deduce their template arguments from the function argument type (i.e. of the type of the RHS of the assignment-expression).

Without a conversion operator in Foo, none of those assignment-operators are viable for std::tie(a,b) = foo.
If you add a conversion operator to Foo,
then only the default assignment-operator becomes viable:
Template type deduction does not take user-defined conversions into account.
That is, you cannot deduce template arguments for the assignment-operator templates from the type Foo.

Since only one user-defined conversion is allowed in an implicit conversion sequence, the type the conversion operator converts to must match the type of the default assignment operator exactly. That is, it must use the exact same tuple element types as the result of std::tie.

To support conversions of the element types (e.g. assignment of Foo::a to a long), the conversion operator of Foo has to be a template:

struct Foo {
    int a;
    string b;
    template<typename T, typename U>
    operator std::tuple<T, U>();
};

However, the element types of std::tie are references.
Since you should not return a reference to a temporary,
the options for conversions inside the operator template are quite limited
(heap, type punning, static, thread local, etc).

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)