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
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
.
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.