Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ macro to replace .at() with []

Tags:

c++

I often have an index out of bounds error that could easily be caught if I used .at() instead of [] to access an element in a vector or string. However, at() slows down my program by a factor of 5 because of bounds checking.

I am trying to write a macro to replace .at(someVariable) with [someVariable] this way I can just uncomment the macro instead of replacing each .at() with a [] manually. I have read the documentation on macros on cppreference.com but can't seem to devise a way to get this functionality.

like image 335
user3586940 Avatar asked Mar 14 '26 06:03

user3586940


2 Answers

In general I'd avoid this kind of macros, as they are "invisible" (so the altered semantics is subtly hidden from anyone not in the knows) and can alter functionality of code that actually expected at to throw on out of bounds, even in release builds. If anything, I'd define something that stands out, for example an all-uppercase AT.

Fortunately, this is not actually needed, as the "big three" C++ runtimes already have builtin functionality to conditionally enable boundary checking on operator[] (which has also the advantage of being more readable than at):

  • if you are using g++/libstdc++ if you pass -​D_GLIBCXX_DEBUG you get the debug version of STL containers, which perform boundary checks on operator[], plus a lot of other debug checks on iterators;
  • CLang/libc++ can do similar checks setting _LIBCPP_DEBUG to 1;
  • for Visual C++ the analogous functionality is enabled with ITERATOR_DEBUG_LEVEL set to 2 (and it's already enabled by default in debug builds).

Incidentally, some of these errors (those that actually overflow the allocated size, not just the "logically valid" size of the vector) may also be spotted using the address sanitizer (-fsanitize=address on gcc and clang) or valgrind (slow!) and similar tools.

like image 76
Matteo Italia Avatar answered Mar 15 '26 21:03

Matteo Italia


Here's one way that does not involve macros - it uses c++17's if constexpr for ease:

#include <vector>

constexpr bool safe_mode = true;  // or false

template<class Container>
auto at(Container& v, std::size_t i) -> decltype(auto)
{
    if constexpr (safe_mode)
        return v.at(i);
    else
        return v[i];
}

int& test(std::vector<int>& v)
{
    return at(v, 6);
}
like image 28
Richard Hodges Avatar answered Mar 15 '26 20:03

Richard Hodges



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!