Re: Variadic function to propagate array indexing doesn't work
correctly
Am 16.04.2012 16:00, schrieb Daryle Walker:
[..]
Note that, for now, I just working with built-in arrays. I checked
my copy of C++2003, and it says that pointer indexing (which
conceptually includes array indexing) works with one pointer(/array)
operand and one integer or enumeration operand. If that's changed
for C++2011, let me know.
This is correct, but there is an issue in progress,
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1454
that will extend the concept of integral constant expressions. In
particular, literal class types with conversions will be legal, like
so:
struct L {
int v;
constexpr L(int v) : v(v) {}
constexpr operator int() { return v; }
};
constexpr L c(2);
int arr[c];
gcc 4.8 already accepts this, which - strictly speaking - is an
extension versus the current wording.
It also works when I want to stop indexing a nested array after one
layer. I want to keep the "noexcept" specification, so I don't want
possibly-throwing conversions from UDTs to discrete-scalars. I
enforce this by requiring the index types C++ allows:
//======================================
template< typename T>
struct can_index_array
: std::integral_constant< bool, std::is_integral<T>::value ||
std::is_enum<T>::value>
{};
//======================================
If anyone has a way to make this work with class-types indices, let
us know. (The class-type must have an unambiguous (non-explicit?)
conversion to either one enum-type or one built-in integer type.
And we need to know if that conversion is no-throw.) The limitation
in index types lets me pass them around by-value, without
forwarding.
If you want to pass them around by-value, you also need to test for
no-throw copy/move, I think. To test for the nothrow-convertibility
you may want to use something like
#include <utility>
template<class T, class U>
struct is_nothrow_convertible
{
template<class V>
static void sink(V) noexcept;
template<class V>
static void test(int) noexcept(noexcept(sink<V>(std::declval<T>())));
template<class>
static void test(...) noexcept(false);
static const bool value = noexcept(test<U>(0));
};
and test for is_nothrow_convertible<T, std::size_t> in the
array-subscription context. Combine this with
is_nothrow_convertible<T, T> and is_nothrow_convertible<T&, T>
(depending on whether the argument is forwarded as lvalue or rvalue)
to respect the copy-initialization context of by-value passing.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]