How can one make a variadic-based chained-indexing function?

后端 未结 2 1904
夕颜
夕颜 2021-02-10 00:54

If I have an object a that either a built-in array or a class-type with a suitable operator [], and its returned type can be indexed itself, how should

相关标签:
2条回答
  • 2021-02-10 01:22

    To get the right return value for the slice function, you can create a helper template that computes the correct result type. For example:

    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;
    };
    

    The slice function would then return a SliceResult<...>::Type.

    0 讨论(0)
  • 2021-02-10 01:23

    I've come up with a solution, based on the comment by @luc-danton and answer by @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)... );
    }
    

    I put a full example program up as a Gist. It worked on a web-site compiler running GCC >= 4.7, CLang >= 3.2, and Intel C++ >= 13.0.

    0 讨论(0)
提交回复
热议问题