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'
libstdc++ as __tuple_like<_Tuple> ?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?
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
Tmodels and satisfies the exposition-only concepttuple-likeifremove_cvref_t<T>is a specialization ofarray,complex,pair,tuple, orranges::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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With