How can an array work with a conditional statement?

This is a retelling of my previous post since I changed the question (so it probably was not marked as a new question and was missed). Hope this cuts back too.

I had features like:

#include <cstddef> #include <type_traits> template < typename E, typename T > inline constexpr auto checked_slice( E &&, T &&t ) noexcept -> T && { return static_cast<T &&>(t); } template < typename E, typename T, std::size_t N, typename U, typename ...V > inline constexpr auto checked_slice( E &&e, T (&t)[N], U &&u, V &&...v ) -> typename remove_some_extents<T, sizeof...(V)>::type & { typedef typename std::remove_reference<U>::type u_type; typedef typename std::common_type<u_type, std::size_t>::type cmp_type; return ( u < u_type{} ) || ( static_cast<cmp_type>(u) >= static_cast<cmp_type>(N) ) ? throw e : checked_slice( static_cast<E &&>(e), t[static_cast<U &&>( u )], static_cast<V &&>(v)... ); } 

where remove_some_extents is a custom class template that, as it were, calls the std::remove_extent meta function a specified number of times.

When I tried to run the program, I got a bunch of errors, such as: "The initialization of a link of type Whatever(&)[X][Y] from an expression of type Whatever(*)[Y] " (or Whatever(&)[Z] from Whatever* ). My workaround was converting the conditional expression into an if - else pair (and removing constexpr ).

I'm trying to figure out what's wrong, so I spend around the section on the conditional statement in the C ++ (2011) standard. This section is 5.16. If one of the two possible actions is the throw command (otherwise it is a void expression), then the condition has the type of another expression, but standard transformations, including from an array to a pointer, are applied to this other expression. (This is in paragraph 2.) I think they confuse me. Is there any way around this? I thought returning an array reference suppresses the a-to-p conversion. Why does it work when it turns into if/else ?

+3
source share
1 answer

Your analysis is correct. I suspect that the non- void operand is “decomposed” (that is, normal conversions) in such a situation as to mimic what happens when two operands differ in type — in the latter case, more often than not all the conditional expression is prvalue.

One situation in which we know the exact category and type of conditional expression is that both operands are exact matches, so we can use this to our advantage:

 cond ? (throw e, t) : t 

will be the lvalue of the array reference type. (Of course, the last operand should not be literally t - you can hook up a recursive call here just fine.)

You did not have such an obstacle when using if / else , because as an operator, the language should not indicate a common type and category of values ​​for it.

+4
source

All Articles