boost:array lacks a statically-checked get()

Reading the archives, I see that the idea of adding a template <unsigned i> T get(); function to boost::array has been somewhat summarily rejected as unnecessary: http://lists.boost.org/boost-users/2005/08/12983.php et seq. And yet I'm finding myself wanting it repeatedly. Here are three places I've seen it crop up: (1) My current application is an arbitrary-dimensional geometry code. I want it to be a template argument what dimension we live in (2, 3, 4, ...). In d dimensions, a simplex has d+1 vertices on it, a point has d coordinates, and an face is a (d-1)-dimensional simplex that has d vertices. You can imagine the potential for off-by-one bugs (personally, I need not imagine). These get caught at runtime when using the array operator[], but I'd rather they be caught at compile time when possible. Therefore, when I'm feeling caffeinated, I write the appropriate BOOST_STATIC_ASSERT (which is of course itself sometimes off by one). (2) I've seen (and written) rather a lot of GUI, networking, and cross-language glue where a common idiom is to have an array of function pointers. Sometimes, the 'name' of the function is an integer read in at runtime. Sometimes, it is known at compile-time. Typically I've seen this implemented using an enum; calling function i is then functions[i](args), whereas calling function foo is functions[FOO](args). The former one can only be checked at run-time. The latter one should be checked at compile-time. It's fine for me to force me to write it as functions.get<FOO>(args) to get compile-time checking, but I do not want to be forced to change both entry FOO in the array, and every call to foo() elsewhere, if I change the name of the function (i.e. during debugging). When I've done this in the past, I've been living in C-land or C++ without boost, so the idea of compile-time checking didn't even occur to me (and, of course, bugs cropped up all the time). (3) Sometimes I don't need an array at all -- I just want a tuple with all values the same type. It's far handier to declare that type as array<foo, 4> than as tuple<foo, foo, foo, foo>. Also, we can now also use the uber-delicious BOOST_FOREACH on the array, which can't be done on the tuple. Summarizing: whenever a client wants to use both integers and names to access a field, array::get<> is useful and matches the boost philosophy of compile-time checking over runtime checking. The change is small in terms of LOC, and does not affect any code outside this one function (and, as far as I can determine, is even ABI-compatible with the prior array code). The runtime implication is nil. -- Benoît

On 6/3/07, Benoit Hudson <benoit.hudson@gmail.com> wrote:
Reading the archives, I see that the idea of adding a template <unsigned i> T get(); function to boost::array has been somewhat summarily rejected as unnecessary: http://lists.boost.org/boost-users/2005/08/12983.php et seq.
And yet I'm finding myself wanting it repeatedly. Here are three places I've seen it crop up:
Isn't this functionality available using the boost::fusion extension for array? You might want to take a look at boost::fusion. Chris

On 6/4/07, Chris Weed <chrisweed@gmail.com> wrote:
On 6/3/07, Benoit Hudson <benoit.hudson@gmail.com> wrote:
Reading the archives, I see that the idea of adding a template <unsigned i> T get(); function to boost::array has been somewhat summarily rejected as unnecessary: http://lists.boost.org/boost-users/2005/08/12983.php et seq.
And yet I'm finding myself wanting it repeatedly. Here are three places I've seen it crop up:
Isn't this functionality available using the boost::fusion extension for array? You might want to take a look at boost::fusion. Chris
Doesn't appear to. The following compiles against CVS of 5 minutes ago, without error: #include <boost/array.hpp> #include <boost/fusion/sequence/adapted.hpp> #include <boost/fusion/sequence/intrinsic.hpp> boost::array<int, 3> arr = {{ 1, 2, 3}}; int x() { // arr[4] return boost::fusion::at_c<4>(arr); } It compiles down to a call to __assert_fail, which is the same behaviour as just using arr[4]. -- Benoît

On 6/5/07, Benoit Hudson <benoit.hudson@gmail.com> wrote:
On 6/4/07, Chris Weed <chrisweed@gmail.com> wrote:
On 6/3/07, Benoit Hudson <benoit.hudson@gmail.com> wrote:
Reading the archives, I see that the idea of adding a template <unsigned i> T get(); function to boost::array has been somewhat summarily rejected as unnecessary: http://lists.boost.org/boost-users/2005/08/12983.php et seq.
And yet I'm finding myself wanting it repeatedly. Here are three places I've seen it crop up:
Isn't this functionality available using the boost::fusion extension for array? You might want to take a look at boost::fusion. Chris
Doesn't appear to. The following compiles against CVS of 5 minutes ago, without error: #include <boost/array.hpp> #include <boost/fusion/sequence/adapted.hpp> #include <boost/fusion/sequence/intrinsic.hpp>
boost::array<int, 3> arr = {{ 1, 2, 3}};
int x() { // arr[4] return boost::fusion::at_c<4>(arr); }
It compiles down to a call to __assert_fail, which is the same behaviour as just using arr[4].
Following all the #includes and templates, I guess it's that boost/fusion/sequence/adapted/array/detail/at_impl.hpp lines 36-40 should probably have a BOOST_STATIC_ASSERT in there? -- Benoît

Doesn't appear to. The following compiles against CVS of 5 minutes ago, without error: #include <boost/array.hpp> #include <boost/fusion/sequence/adapted.hpp> #include <boost/fusion/sequence/intrinsic.hpp>
boost::array<int, 3> arr = {{ 1, 2, 3}};
int x() { // arr[4] return boost::fusion::at_c<4>(arr); }
It compiles down to a call to __assert_fail, which is the same behaviour as just using arr[4].
Following all the #includes and templates, I guess it's that boost/fusion/sequence/adapted/array/detail/at_impl.hpp lines 36-40 should probably have a BOOST_STATIC_ASSERT in there?
-- Benoît
You might want to drop an email to the boost devel list about possibly changing this for fusion. This makes sense to me, but the developers of fusion might think otherwise. Chris
participants (2)
-
Benoit Hudson
-
Chris Weed