T (&&arr)[N] is not a forwarding reference, so you shouldn’t use std::forward here. Use std::move, because you intend to take this lvalue and (unconditionally) turn it into an rvalue; that’s what std::move is for.

You’re totally right, @Arthur, thanks. I messed it up quite badly. So here you are what a (hopefully correct) r-value specialization may look like:

template <std::size_t Idx, typename T, std::size_t N>
constexpr T&& get(T (&&arr)[N]) noexcept
{
    static_assert(Idx < N, "Index out of bounds");
    return std::move(arr)[Idx];
}

@Lénárd’s observation about MSVC raises the question whether the return type should be T&& or decltype(auto). In the latter case, calling get on an r-value C-style array would return an l-value (on MSVC).

Again, I’d stick to what the standard already mandates for std::array. So, in my opinion, the above specialization should return T&&.

Moreover, the decltype(auto) version would instanciate functions with different signatures on different compilers, e.g.:

constexpr int&  get<0, int, 3>(int (&&)[3]) noexcept; // MSVC
constexpr int&& get<0, int, 3>(int (&&)[3]) noexcept; // Clang/GCC

I’m not really sure whether this is an issue, since the return type of std::move(arr)[Idx] itself is not consistent across compilers.

As for the rest of the tuple-like interface for T[N], I’ve come up with this:

namespace std
{

template <typename T, size_t N>
struct tuple_size<T[N]>
    : public integral_constant<size_t, N> { };

// I have to add the following explicit specialization. If I don't,
// tuple_size<T const[N]> would match both the following
// specializations:
//
//  1. <U[N]> with U = T const (i.e. the specialization above);
//  2. <U const> with U = T[N] (alredy in the standard).
// 
// Resulting in a compiler error.
template <typename T, size_t N>
struct tuple_size<T const[N]> : public tuple_size<T[N]> { };

template <typename T, size_t N>
struct tuple_size<T volatile[N]> : public tuple_size<T[N]> { };

template <typename T, size_t N>
struct tuple_size<T const volatile[N]> : public tuple_size<T[N]> { };
// --

namespace detail
{
    template <size_t Idx, typename T>
    struct array_tuple_element;

    template <size_t Idx, typename T, size_t N>
    struct array_tuple_element<Idx, T[N]>
    {
        static_assert(Idx < N, "Index out of bounds");
        using type = T;
    };
}

template <size_t Idx, typename T, size_t N>
struct tuple_element<Idx, T[N]>
    : public detail::array_tuple_element<Idx, T[N]> { };

// -- I have to specify those for the same reason above.
template <size_t Idx, typename T, size_t N>
struct tuple_element<Idx, T const[N]>
    : public detail::array_tuple_element<Idx, T const[N]> { };

template <size_t Idx, typename T, size_t N>
struct tuple_element<Idx, T volatile[N]>
    : public detail::array_tuple_element<Idx, T volatile[N]> { };

template <size_t Idx, typename T, size_t N>
struct tuple_element<Idx, T const volatile[N]>
    : public detail::array_tuple_element<Idx, T const volatile[N]> { };
// --
}

As suggested by @Zhihao, it’s true that a tuple-like interface is not needed for structured bindings to C-style arrays. However, it would allow for:

Here you are a link to play with:

https://godbolt.org/z/Ts3fn3YT4

(Note: I had to specialize struct std::__is_tuple_like_impl for T[N] in order to pass "bye" to std::tuple_cat on Clang/GCC).


Il giorno mar 1 mar 2022 alle ore 19:36 Zhihao Yuan via Std-Proposals <std-proposals@lists.isocpp.org> ha scritto:
On Tuesday, March 1st, 2022 at 10:25 AM, Lénárd Szolnoki via Std-Proposals <std-proposals@lists.isocpp.org> wrote:

> > [...] Structured bindings have dedicated
> > rules for C arrays[dcl.struct.bind] (eel.is) and it kicks inearly,
> > ignoring all tuple_* stuff.
>

> As you write, it wouldn't do anything for structured bindings, but it
> would enable C arrays for `std::apply`.
>


Cool! Love to see it.

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
_______________________________________________
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals