Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::apply to a custom, tuple-like type

This problem was encountered while upgrading a C++17 codebase to C++23. The code size is significant (100k+), it is rather technical and quite template-heavy.

On a rather central location, we use std::apply to invoke functors on arguments, which come in various flavours, be it as std::tuple, sometimes as std::array, and sometimes in custom data types with very specific memory layout, which conform to the »tuple protocol« (and are also used a lot in structured bindings). For context, we use partial function closure to "partially close" some of those arguments, while other arguments will be supplied late, after a runtime dynamic dispatch.

Now, with GCC-14 and -std=gnu++23 (on Linux / Debian), the code is rejected with

error: no matching function for call to 'apply(...<line-noise elided>...'
note: candidate: 'template<class _Fn, class _Tuple>  requires  __tuple_like<_Tuple> constexpr decltype(auto) std::apply(_Fn&&, _Tuple&&)'

note: template argument deduction/substitution failed:
note: constraints not satisfied

In substitution of template ..... requires  __tuple_like<_Tuple> ... apply(
note: the expression '__is_tuple_like_v<...custom type here...>' evaluated to 'false'

Questions

  • How can a custom-made type, which conforms to the tuple protocol, fulfil this exposition only concept, which is implemented in the GNU libstdc++ as __tuple_like<_Tuple> ?
  • how was that situation intended to work and be handled by the current (or future) standards?
  • does anyone know why the standard does not provide a real tuple_like concept in the header <concepts>. Are there any pitfalls and nasty dragons hidden somewhere?

Looking into the implementation of libstdc++ I was rather flabbergasted to find a gem like

template<typename... _Tps>
struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
{ };

Wasn't the idea with type classes, or concepts (which intentionally aim in the same direction, while there are fine differences): that a given piece of code works with any type that fulfils some relations and constraints...?

And now I seem only to find code in the standard library, where some authority tells me: "here are 5 of our implementations, where we tell you that they are OK".

So the deeper question is: am I expecting too much here? Is the implementation not up to the game yet?

Shall I just stop worrying and roll my own apply function, together with a real tuple_like concept?

There are various examples available, see e.g. this question. I am fairly experienced, yet rather new to concepts (but know Haskell and Scala), so I'll be able to cope with that. Sounds like a bad idea?

like image 299
Ichthyo Avatar asked Oct 23 '25 15:10

Ichthyo


1 Answers

How can a custom-made type, which conforms to the tuple protocol, fulfil this exposition only concept, which is implemented in the GNU libstdc++ as __tuple_like<_Tuple> ?

You cannot. tuple-like is defined as:

A type T models and satisfies the exposition-only concept tuple-like if remove_cvref_t<T> is a specialization of array, complex, pair, tuple, or ranges​::​subrange.

Your custom type is none of those.

how was that situation intended to work and be handled by the current (or future) standards?

It was never intended to work. But it's easy enough to implement your own apply.

like image 114
Barry Avatar answered Oct 25 '25 05:10

Barry