Note: I solved the original problem by realizing a completely different one. See the addendum for the new actual problem, but you can read the previous part for context.
This is an extension of one of my previous posts. I made a container class based on that answer:
template < typename T, unsigned N0, unsigned ...N >
struct array_md
{
// There's a class template specialization with no extents.
// Imagine the various N... components are bracket-enclosed instead
// of comma-separated. And if "N..." is empty, then we just have "T"
// as the "direct_element_type". (I actually use recursive class
// definitions.)
using direct_element_type = T[N...];
using data_type = direct_element_type[ N0 ];
template < typename ...Indices >
auto operator ()( Indices &&...i )
noexcept( !indexing_result<data_type &, Indices...>::can_throw )
-> typename indexing_result<data_type &, Indices...>::type
{ return slice(data, static_cast<Indices &&>( i )...); }
template < typename ...Indices >
constexpr
auto operator ()( Indices &&...i ) const
noexcept( !indexing_result<data_type &, Indices...>::can_throw )
-> typename indexing_result<data_type &, Indices...>::type
{ return slice(data, static_cast<Indices &&>( i )...); }
data_type data;
};
I'm trying to make a version of at
for this container. I figured I'll just make a version of slice
that takes an exception object. Unlike the general slice
, my checked_slice
has to take in a built-in array object, since pointers and class types (with operator []
) don't have a (standard) way to give me bounds.
template < typename E, typename T >
inline constexpr
auto checked_slice( E &&, T &&t ) noexcept -> T &&
{ return static_cast<T &&>(t); }
template < typename E, typename T, std::size_t N, typename ...V >
inline constexpr
auto checked_slice( E &&e, T (&t)[N], std::size_t u, V &&...v )
-> typename remove_some_extents<T[N], 1u + sizeof...(V)>::type &
{
return u < N ? checked_slice( static_cast<E &&>(e), static_cast<T &>(t[ u ]),
static_cast<V &&>(v)... ) : throw static_cast<E &&>( e );
}
template < typename E, typename T, std::size_t N, typename ...V >
inline constexpr
auto checked_slice( E &&e, T (&&t)[N], std::size_t u, V &&...v )
-> typename remove_some_extents<T[N], 1u + sizeof...(V)>::type &&
{
return u < N ? checked_slice( static_cast<E &&>(e),static_cast<T &&>(t[ u ]),
static_cast<V &&>(v)... ) : throw static_cast<E &&>( e );
}
(The remove_some_extents
does what it says, instead of just one or all the C++11 standard library gives you.) When I put this into my at
:
template < typename T, unsigned N0, unsigned ...N >
struct array_md
{
//...
template < typename ...Indices >
auto at( Indices &&...i )
-> typename remove_some_extents<data_type, sizeof...( Indices )>::type &
{
return checked_slice(std::out_of_range{ "Index out of bounds" }, data,
static_cast<Indices &&>( i )...);
}
template < typename ...Indices >
constexpr
auto at( Indices &&...i ) const
-> typename remove_some_extents<data_type,sizeof...( Indices )>::type const &
{
return checked_slice(std::out_of_range{ "Index out of bounds" }, data,
static_cast<Indices &&>( i )...);
}
//...
};
I get errors related to array-to-pointer decay! (I'm using TDC-GCC 4.7.1 that's bundled with CodeBlocks 12.11 for Windows-8 Pro 32-bit.)
In file included from container/array_md.hpp:36:0,
from test\arraymd_test.cpp:15:
utility/slice.hpp: In instantiation of 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const int; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const int; std::size_t = unsigned int]':
container/array_md.hpp:284:112: required from 'constexpr const typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type& container::array_md<T, M, N ...>::at(Indices&& ...) const [with Indices = {int}; T = int; unsigned int M = 2u; unsigned int ...N = {}; typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type = int]'
test\arraymd_test.cpp:224:1: required from here
utility/slice.hpp:141:10: warning: returning reference to temporary [enabled by default]
utility/slice.hpp: In instantiation of 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [2][6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [2][6]; std::size_t = unsigned int]':
container/array_md.hpp:284:112: required from 'constexpr const typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type& container::array_md<T, M, N ...>::at(Indices&& ...) const [with Indices = {int}; T = char [6]; unsigned int M = 2u; unsigned int ...N = {2u}; typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type = char [2][6]]'
test\arraymd_test.cpp:238:1: required from here
utility/slice.hpp:141:10: error: invalid initialization of reference of type 'const char (&)[2][6]' from expression of type 'const char (*)[6]'
utility/slice.hpp:142:1: error: body of constexpr function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [2][6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [2][6]; std::size_t = unsigned int]' not a return-statement
utility/slice.hpp: In instantiation of 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [6]; std::size_t = unsigned int]':
utility/slice.hpp:141:10: required from 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [2][6]; unsigned int N = 2u; V = {int}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [6]; std::size_t = unsigned int]'
container/array_md.hpp:284:112: required from 'constexpr const typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type& container::array_md<T, M, N ...>::at(Indices&& ...) const [with Indices = {int, int}; T = char [6]; unsigned int M = 2u; unsigned int ...N = {2u}; typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type = char [6]]'
test\arraymd_test.cpp:239:1: required from here
utility/slice.hpp:141:10: error: invalid initialization of reference of type 'const char (&)[6]' from expression of type 'const char*'
utility/slice.hpp:142:1: error: body of constexpr function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [6]; std::size_t = unsigned int]' not a return-statement
utility/slice.hpp: In instantiation of 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [2][6]; unsigned int N = 2u; V = {int}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [6]; std::size_t = unsigned int]':
container/array_md.hpp:284:112: required from 'constexpr const typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type& container::array_md<T, M, N ...>::at(Indices&& ...) const [with Indices = {int, int}; T = char [6]; unsigned int M = 2u; unsigned int ...N = {2u}; typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type = char [6]]'
test\arraymd_test.cpp:239:1: required from here
utility/slice.hpp:141:10: error: invalid initialization of reference of type 'const char (&)[6]' from expression of type 'const char*'
utility/slice.hpp:142:1: error: body of constexpr function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [2][6]; unsigned int N = 2u; V = {int}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [6]; std::size_t = unsigned int]' not a return-statement
utility/slice.hpp: In instantiation of 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [2][6]; unsigned int N = 2u; V = {unsigned int}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [6]; std::size_t = unsigned int]':
container/array_md.hpp:284:112: required from 'constexpr const typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type& container::array_md<T, M, N ...>::at(Indices&& ...) const [with Indices = {int, unsigned int}; T = char [6]; unsigned int M = 2u; unsigned int ...N = {2u}; typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type = char [6]]'
test\arraymd_test.cpp:261:5: required from here
utility/slice.hpp:141:10: error: invalid initialization of reference of type 'const char (&)[6]' from expression of type 'const char*'
utility/slice.hpp:142:1: error: body of constexpr function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [2][6]; unsigned int N = 2u; V = {unsigned int}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [6]; std::size_t = unsigned int]' not a return-statement
utility/slice.hpp: In instantiation of 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = int; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = int; std::size_t = unsigned int]':
container/array_md.hpp:274:112: required from 'typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type& container::array_md<T, M, N ...>::at(Indices&& ...) [with Indices = {int}; T = int; unsigned int M = 2u; unsigned int ...N = {}; typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type = int]'
test\arraymd_test.cpp:220:1: required from here
utility/slice.hpp:141:10: error: invalid initialization of non-const reference of type 'remove_some_extents<int [2], 1u>::type& {aka int&}' from an rvalue of type 'int'
utility/slice.hpp:142:1: error: body of constexpr function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = int; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = int; std::size_t = unsigned int]' not a return-statement
utility/slice.hpp: In instantiation of 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [2][6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [2][6]; std::size_t = unsigned int]':
container/array_md.hpp:274:112: required from 'typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type& container::array_md<T, M, N ...>::at(Indices&& ...) [with Indices = {int}; T = char [6]; unsigned int M = 2u; unsigned int ...N = {2u}; typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type = char [2][6]]'
test\arraymd_test.cpp:234:1: required from here
utility/slice.hpp:141:10: error: invalid initialization of non-const reference of type 'char (&)[2][6]' from an rvalue of type 'char (*)[6]'
utility/slice.hpp:142:1: error: body of constexpr function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [2][6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [2][6]; std::size_t = unsigned int]' not a return-statement
utility/slice.hpp: In instantiation of 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [6]; std::size_t = unsigned int]':
utility/slice.hpp:141:10: required from 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [2][6]; unsigned int N = 2u; V = {int}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [6]; std::size_t = unsigned int]'
container/array_md.hpp:274:112: required from 'typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type& container::array_md<T, M, N ...>::at(Indices&& ...) [with Indices = {int, int}; T = char [6]; unsigned int M = 2u; unsigned int ...N = {2u}; typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type = char [6]]'
test\arraymd_test.cpp:235:1: required from here
utility/slice.hpp:141:10: error: invalid initialization of non-const reference of type 'char (&)[6]' from an rvalue of type 'char*'
utility/slice.hpp:142:1: error: body of constexpr function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [6]; std::size_t = unsigned int]' not a return-statement
utility/slice.hpp: In instantiation of 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [2][6]; unsigned int N = 2u; V = {int}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [6]; std::size_t = unsigned int]':
container/array_md.hpp:274:112: required from 'typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type& container::array_md<T, M, N ...>::at(Indices&& ...) [with Indices = {int, int}; T = char [6]; unsigned int M = 2u; unsigned int ...N = {2u}; typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type = char [6]]'
test\arraymd_test.cpp:235:1: required from here
utility/slice.hpp:141:10: error: invalid initialization of non-const reference of type 'char (&)[6]' from an rvalue of type 'char*'
utility/slice.hpp:142:1: error: body of constexpr function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [2][6]; unsigned int N = 2u; V = {int}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [6]; std::size_t = unsigned int]' not a return-statement
utility/slice.hpp: In instantiation of 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [2][6]; unsigned int N = 2u; V = {long double}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [6]; std::size_t = unsigned int]':
container/array_md.hpp:274:112: required from 'typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type& container::array_md<T, M, N ...>::at(Indices&& ...) [with Indices = {int, long double}; T = char [6]; unsigned int M = 2u; unsigned int ...N = {2u}; typename remove_some_extents<typename container::array_md<T, N ...>::data_type [M], sizeof (Indices ...)>::type = char [6]]'
test\arraymd_test.cpp:260:5: required from here
utility/slice.hpp:141:10: error: invalid initialization of non-const reference of type 'char (&)[6]' from an rvalue of type 'char*'
utility/slice.hpp:142:1: error: body of constexpr function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [2][6]; unsigned int N = 2u; V = {long double}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [6]; std::size_t = unsigned int]' not a return-statement
utility/slice.hpp: In function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [2][6]; unsigned int N = 2u; V = {unsigned int}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [6]; std::size_t = unsigned int]':
utility/slice.hpp:142:1: warning: control reaches end of non-void function [-Wreturn-type]
utility/slice.hpp: In function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [2][6]; unsigned int N = 2u; V = {int}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [6]; std::size_t = unsigned int]':
utility/slice.hpp:142:1: warning: control reaches end of non-void function [-Wreturn-type]
utility/slice.hpp: In function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [6]; std::size_t = unsigned int]':
utility/slice.hpp:142:1: warning: control reaches end of non-void function [-Wreturn-type]
utility/slice.hpp: In function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = const char [2][6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = const char [2][6]; std::size_t = unsigned int]':
utility/slice.hpp:142:1: warning: control reaches end of non-void function [-Wreturn-type]
utility/slice.hpp: In function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [2][6]; unsigned int N = 2u; V = {long double}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [6]; std::size_t = unsigned int]':
utility/slice.hpp:142:1: warning: control reaches end of non-void function [-Wreturn-type]
utility/slice.hpp: In function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [2][6]; unsigned int N = 2u; V = {int}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [6]; std::size_t = unsigned int]':
utility/slice.hpp:142:1: warning: control reaches end of non-void function [-Wreturn-type]
utility/slice.hpp: In function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [6]; std::size_t = unsigned int]':
utility/slice.hpp:142:1: warning: control reaches end of non-void function [-Wreturn-type]
utility/slice.hpp: In function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = char [2][6]; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = char [2][6]; std::size_t = unsigned int]':
utility/slice.hpp:142:1: warning: control reaches end of non-void function [-Wreturn-type]
utility/slice.hpp: In function 'constexpr typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type& checked_slice(E&&, T (&)[N], std::size_t, V&& ...) [with E = std::out_of_range; T = int; unsigned int N = 2u; V = {}; typename remove_some_extents<T [N], (1u + sizeof (V ...))>::type = int; std::size_t = unsigned int]':
utility/slice.hpp:142:1: warning: control reaches end of non-void function [-Wreturn-type]
I thought using array references cancels array-to-pointer decay. Is this a GCC bug, or am I messing up somewhere?
For "slice.hpp", Line 141, Col. 10 is the end of the statement in the (l-value version of) checked_slice
function, while L142C1 is the function's ending bracket. In "array_md.hpp", L284C112 and L274C112 are return (and sole) statements of the at
functions, const
and non-const respectively. The column is at the "i" inside the static_cast
.
By the way, here's remove_some_extents
:
// Forward declaration
template < typename Array, std::size_t Count >
struct remove_some_extents;
// Case with indefinite array but no extents to strip
template < typename T >
struct remove_some_extents< T[], 0u >
{ typedef T type[]; };
// Case with definite array but no extents to strip
template < typename T, std::size_t N >
struct remove_some_extents< T[N], 0u >
{ typedef T type[N]; };
// Case with non-array type but no extents to strip
template < typename T >
struct remove_some_extents< T, 0u >
{ typedef T type; };
// Case with indefinite array and extents to strip
template < typename T, std::size_t L >
struct remove_some_extents< T[], L >
{ typedef typename remove_some_extents<T, L - 1u>::type type; };
// Case with definite array and extents to strip
template < typename T, std::size_t N, std::size_t L >
struct remove_some_extents< T[N], L >
{ typedef typename remove_some_extents<T, L - 1u>::type type; };
// Right now, non-array type with non-zero strip count should give an error.
Thanks.
Edit: Added the base-case and r-value overloads for checked_slice
.
Addendum: I got something that works, but I don't know why the old way didn't work.
I first commented out the r-value overload for checked_slice
, to reduce the variables I have to work with. I then made a version of checked_slice
that works for standard containers, but you don't need to see it because it didn't help. (And I commented it out to make sure it didn't make a difference.)
I changed the regular version to:
template < typename E, typename T, std::size_t N, typename ...V >
inline constexpr
auto checked_slice( E &&e, T (&t)[N], std::size_t u, V &&...v )
-> typename remove_some_extents<T[N], 1u + sizeof...(V)>::type &
{
return checked_slice( static_cast<E &&>(e), static_cast<T &>(t[ u ]),
static_cast<V &&>(v)... );
}
i.e. I removed the actual test and the throw-on-fail parts, and the code worked! The problem didn't seem to be the indexing, but the throw and/or conditional! Sure enough, when I changed it to:
template < typename E, typename T, std::size_t N, typename ...V >
inline
auto checked_slice( E &&e, T (&t)[N], std::size_t u, V &&...v )
-> typename remove_some_extents<T[N], 1u + sizeof...(V)>::type &
{
if ( u < N )
return checked_slice(static_cast<E &&>(e),t[u],static_cast<V &&>(v)...);
else
throw e;
}
It still works! What gives, I thought it was OK to use a throw statement as one of the action parts of a conditional expression? Is it a bug in my compiler?
I may have to give up and separate the bounds-check to a pure-function and throw-on-fail within the at
method.
Since I changed this question, it may have not been flagged as a new one. I got an answer from re-asking in another post, and it worked.
来源:https://stackoverflow.com/questions/16163456/can-you-throw-within-a-conditional-expression-was-how-can-bounds-checking-be