How can I make a function of coding with reference to variations?

If I have an object a, then either an inline array or a class type with a suitable one operator [], and its return type can be indexed myself, how can I write a general function that can index all of them with a variable call instead of a separate block of brackets? In other words, I can make expressions such as:

a[i0][i1]...[iK]

and I want to be able to write it as one function:

slice( a, i0, i1, ..., iK )

since C ++ rules require it to operator []work with single arguments, making it less compatible with variable material. (This question is based on the Usenet thread, where I tried asking for something like this, ultimately resolving only possible nested built-in arrays.)

First hit:

template < typename T, typename U >
constexpr
auto slice( T &&t, U &&u ) noexcept(???) -> ???
{ return ce_forward<T>(t)[ ce_forward<U>(u) ]; }

template < typename T, typename U, typename V, typename ...W >
constexpr
auto slice( T &&t, U &&u, V &&v, W... &&w ) noexcept(???) -> ???
{
    return slice( ce_forward<T>(t)[ce_forward<U>(u)], ce_forward<V>(v),
     ce_forward<W>(w)... );
}

ce_forward constexpr - std::forward. ( , constexpr, .) , . , , :

  • operator [] , ( ), - . . , ( ?) .
  • operator [] - (-). ( this).
  • . ( UDT, .) undefined, , .
  • l-, r slice.
  • (final?) , std::is_nothrow_move_constructible<ReturnType>::value OR'd . ( - noexcept.)
  • , r-, . ( , , , l-v-r-value, l-value.)
  • , ( ), . , this (const/volatile/both/none / &/&&/none).
+5
2

, @luc-danton @user315052.

#include <utility>

template < typename Base, typename ...Indices >
class indexing_result;

template < typename T >
class indexing_result<T>
{
public:
    using type = T;

    static constexpr
    bool  can_throw = false;
};

template < typename T, typename U, typename ...V >
class indexing_result<T, U, V...>
{
    using direct_type = decltype( std::declval<T>()[std::declval<U>()] );
    using   next_type = indexing_result<direct_type, V...>;

    static constexpr
    bool  direct_can_throw
     = not noexcept( std::declval<T>()[std::declval<U>()] );

public:
    using type = typename next_type::type;

    static constexpr
    bool  can_throw = direct_can_throw || next_type::can_throw;
};

template < typename T >
inline constexpr
auto  slice( T &&t ) noexcept -> T &&
{ return static_cast<T &&>(t); }

template < typename T, typename U, typename ...V >
inline constexpr
auto  slice( T &&t, U &&u, V &&...v )
  noexcept( !indexing_result<T, U, V...>::can_throw )
  -> typename indexing_result<T, U, V...>::type
{
    return slice( static_cast<T &&>(t)[static_cast<U &&>( u )],
     static_cast<V &&>(v)... );
}

Gist. -, GCC >= 4.7, CLang >= 3.2 Intel ++ >= 13.0.

+3

slice, , . :

template <typename T, typename U, typename... V>
struct SliceResult {
    typedef typename SliceResult<T, V...>::Type Type;
};

template <typename T, typename U>
struct SliceResult<T, U> {
    typedef typename std::underlying_type<T[U(0)]>::type Type;
};

slice SliceResult<...>::Type.

+1

All Articles