   using arrays with the STL
  From time to time, I find myself writing code like this:#include <algorithm>#include <iostream>#include <boost/lambda/lambda.hpp>using namespace boost::lambda;int main(){    char const* test[] = {"Hello", "Beautiful", "World"};    std::for_each(test, test + 3, std::cout << _1 << "\n"); // interesting line}How do I make sure the expression "test + 3" actually marks the end of the array? After some thinking, I wrote the following pair of inline function templates:#include <algorithm>#include <iostream>#include <boost/lambda/lambda.hpp>using namespace boost::lambda;template<typename T, size_t n>inline T const* end_of(T const (&a)[n]){    return a + n;}template<typename T, size_t n>inline T* end_of(T (&a)[n]){    return a + n;}int main(){    char const* test[] = {"Hello", "Beautiful", "World"};    std::for_each(test, end_of(test), std::cout << _1 << "\n");}Now I'm almost 100% sure that hundreds of other programmers have discovered that trick before me, but I still wanted to share it with you and ask your opinion about it.On a sidenote, do you think it's good practice to write these short const/non-const function pairs with repeated code, or should one of them be implemented in terms of the other? I seem to remember Scott Meyers had an item on that very subject. The code would then look something like this:template<typename T, size_t n>inline T const* end_of(T const (&a)[n]){    return a + n;}template<typename T, size_t n>inline T* end_of(T (&a)[n]){    return const_cast<T*>(end_of(static_cast<T const (&)[n]>(a)));}Would you consider this good practice or over-engineering?   
Quote:Now I'm almost 100% sure that hundreds of other programmers have discovered that trick before me, but I still wanted to share it with you and ask your opinion about it.I have a pair of functions, begin() and end(), I think I stole the idea from ToohrVyk. I haven't had cause to overload them in a non-const fashion, I rarely use arrays at all.Since they are one liners, I would just copy/paste and remove the "const". I mean, your alternative is even longer than the original! Not to mention harder to read. It might be a good idea if the actual logic was quite complex however.I don't think there is a clean way to implement one in terms of the other. I would be fascinated if someone has a really neat way to do this.   ;  Hm, I just realized there is no need for the const version, the non-const version should be enough:template<typename T, size_t n>inline T* end_of(T (&a)[n]){    return a + n;}If I pass an array-of-const, the return type will be pointer-to-const automatically.Quote:Original post by rip-offI rarely use arrays at all.With C++0x's std::initializer_list facility, I guess I won't use them anymore either :)   ;  That appears to be how I had it written.I would still be interested in learning if there is a cleaner way of handling duplicate code where the only difference is "const". Of particular interest would be things like operator[], where you have the entire class would be templated so you can't take advantage of that trick.   ;  It seems you're already using boost.Boost already provides that functionality: boost::end(). This will actually work on any container or range.Boost also provides these syntaxesboost::for_each(test, std::cout << _1 << "\n");andBOOST_FOREACH(const char* s, test)    std::cout << s << "\n";;  As for const, it's simply not needed. In your template functions, const can already match as part of T.   ;Quote:Original post by loufoqueBoost already provides that functionality: boost::end().Awesome, didn't know about that. Thanks!   ;Quote:Original post by loufoqueboost::for_each(test, std::cout << _1 << "\n");Which header do I need to include for that?   ;  AFAIK Boost doesn't provide it. You need to #define it yourself ("#define foreach BOOST_FOREACH" will do).   ;  Nah, boost::foreach is nicer than that. It lets you write stuff likeBOOST_FOREACH(int i, test){    std::cout<< i << "\n";}It avoids a bunch of problem stuff with boost::lambda - like the syntax for calling a member function on a bound variable.   