Skip to content

Instantly share code, notes, and snippets.

@CTMacUser
Created April 3, 2013 00:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CTMacUser/5297353 to your computer and use it in GitHub Desktop.
Save CTMacUser/5297353 to your computer and use it in GitHub Desktop.
An example program to create a variadic function that computes a chain of indexing expressions. It's a solution of a problem I posted at http://stackoverflow.com/q/10171525/1010226
/*
Demostration of variadic function template that runs a series of indexing
expressions. Based of a problem I posted at
http://stackoverflow.com/q/10171525/1010226
Copyright (C) 2013 Daryle Walker
I'm letting anyone use this code under the Boost Software License.
*/
#include <cassert>
#include <cstddef>
#include <string>
#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)... );
}
template < typename T, std::size_t N >
struct my_array
{
T data[ N ];
T & operator []( std::size_t i ) noexcept(false)
{ return this->data[i]; }
constexpr
auto operator []( std::size_t i ) const noexcept -> T const &
{ return data[i]; }
};
int main( int, char *[] )
{
char a[] = "abcdefg";
my_array<std::string, 2> b[ 2 ]{ {{ "Hello", "World" }}, {{
"Goodbye", "Planet" }} };
my_array<std::string, 2> const (&c)[ 2 ] = b;
assert( a[0] == 'a' );
assert( 1[a] == 'b' );
assert( slice(a, 2) == 'c' );
assert( slice(3, a) == 'd' );
a[ 4 ] = 'E';
assert( slice(a, 4) != 'e' );
assert( slice(4, a) == 'E' );
assert( noexcept(slice( a, 5 )) );
assert( noexcept(slice( 6, a )) );
assert( b[0][0] == "Hello" );
assert( b[0][1][0] == 'W' );
assert( c[1][1][5] == 't' );
assert( 1[c][0][0] == 'G' );
assert( slice(b, 0, 1) == "World" );
assert( slice(1, c, 0) == "Goodbye" );
assert( slice(c, 0, 1, 2) == 'r' );
slice( 0, b, 0, 4 ) = ' ';
assert( slice(c, 0, 0) == "Hell " );
assert( noexcept(slice( b, 1 )) );
assert( !noexcept(slice( b, 1, 0 )) );
assert( !noexcept(slice( b, 1, 0, 2 )) );
assert( noexcept(slice( c, 1 )) );
assert( noexcept(slice( c, 1, 0 )) );
assert( !noexcept(slice( c, 1, 0, 2 )) );
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment