|
Boost : |
From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2000-08-29 03:58:33
Dave Abrahams wrote:
> // Determine the number of elements in an array. Works even with broken
> // compilers that can't resolve the array size as a function template
> // parameter. This is based on a comp.lang.c++.moderated posting by
> "Jonathan
> // Lundquist" <jhl_at_[hidden]>, who gives the following explanation:
> //
> // When invoked with a pointer instead of a true array, the template
> // returning void will be resolved, which will fail the compile.
> //
> // When invoked with an array, the template returning int will be
> // resolved, so sizeof(a) / sizeof((a)[0]) will be evaluated.
> //
> // The '0' term of the expression will never be returned, but is there to
> // complete the syntax of the ?: expression.
> #define BOOST_ARRAY_LENGTH(a) \
> (sizeof(boost::detail::not_an_array_type((a), &(a))) ? sizeof(a) /
> sizeof((a)[0]) : 0)
>
> namespace boost { namespace detail {
> template<typename T>
> void not_an_array_type(T* const, T* const*);
>
> template<typename T>
> int not_an_array_type(const void*, T);
> }}
>
IMO, the check for a pointer, as it is written now, in some cases will
produce ambiguity:
void foo() {
char a[10];
char* p1;
const char* p2;
char* const cp1 = 0;
const char* const cp2 = 0;
BOOST_ARRAY_LENGTH(a); // compiles
BOOST_ARRAY_LENGTH(p1); // ambiguity, fails
BOOST_ARRAY_LENGTH(p2); // ambiguity, fails
BOOST_ARRAY_LENGTH(cp1); // fails
BOOST_ARRAY_LENGTH(cp2); // fails
}
Of course, it'll still fail, but not in the way it was intended. To fix that
we need to add into 'boost::detail' namespace yet other 'not_an_array_type'
function template:
template<typename T>
void not_an_array_type(T* const, T**);
But these are details :). I've seen (and used) a similar macro at least 3
times in 3 different projects, so it might be a good addition... the only
thing to wish is that it wasn't a macro.
--Aleksey
P.S. I've checked my example (with the original implementation of the macro)
on CW5.3 and Comeau C++ 4.2.43. CodeWarrior doesn't say anything about 2
lines that I think must produce ambiguity; I think it is wrong here. Comeau
C++ reports the expected errors, but if I change the first parameter of the
second function template from 'const void*' to 'void*' it reports ambiguity
for only one line - BOOST_ARRAY_LENGTH(p1); I think it is wrong too, or I am
missing something :).
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk