Created
April 3, 2013 00:07
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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