Before I give an example, note a couple of things:

- You've picked some of the best C++ libraries as if they're somehow representative of the ocean of C++ code that's out there, whereas I was talking more about the general landscape.

- It's hard to do an apples-to-apples comparison for a library (like Abseil) that tries to avoid replicating what's already in the standard library, so those aren't necessarily the best examples to discuss here.

That said, OK, here's one trivial example. It is a major time sink to dig these up and write self-contained examples for the sake of argument (it took me 1 hour to write this entire comment), so I hope this example can be sufficient to get my point across.

So folly has FBVector and it supports custom allocators, right? OK, so just try making a vector with a custom pointer type:

#include <vector>

// #include <folly/FBVector.h>

template<class T>
struct my_pointer
{
typedef my_pointer this_type;
typedef T element_type, value_type;
typedef ptrdiff_t difference_type;
typedef this_type pointer;
typedef value_type &reference;
bool operator!=(this_type const &other) const { return !(*this == other); }
bool operator==(this_type const &other) const { return this->p == other.p; }
difference_type operator-(this_type const &other) const { return this->p - other.p; }
explicit operator bool() const { return !!this->p; }
friend this_type operator +(difference_type n, this_type me) { return me + n; }
explicit my_pointer(T *p) : p(p) { }
my_pointer(std::nullptr_t p) : p(p) { }
my_pointer() : p() { }
reference operator *() const { return *this->p; }
template<class U> using rebind = my_pointer<T>;
this_type &operator++() { ++this->p; return *this; }
this_type &operator+=(difference_type n) { this->p += n; return *this; }
this_type &operator--() { --this->p; return *this; }
this_type &operator-=(difference_type n) { this->p -= n; return *this; }
this_type operator+(difference_type d) const { return this_type(this->p + d); }
this_type operator++(int) { this_type copy(*this); ++*this; return copy; }
this_type operator-(difference_type d) const { return this_type(this->p - d); }
this_type operator--(int) { this_type copy(*this); --*this; return copy; }
value_type *operator->() const { return this->p; }
reference operator[](difference_type d) { return this->p[d]; }
private:
T *p;
};

template<class T>
struct my_allocator
{
std::allocator<T> base;
typedef T value_type;
typedef size_t size_type;
typedef my_pointer<T> pointer;
template<class U> struct rebind { typedef my_allocator<U> other; };
pointer allocate(size_type n) { return pointer(this->base.allocate(n)); }
void deallocate(pointer p, size_type n) { return this->base.deallocate(&*p, n); }
};

namespace std
{
template<class T>
struct iterator_traits<my_pointer<T> >
{
typedef typename my_pointer<T>::pointer pointer;
typedef typename my_pointer<T>::reference reference;
typedef typename my_pointer<T>::value_type value_type;
typedef typename my_pointer<T>::difference_type difference_type;
typedef std::random_access_iterator_tag iterator_category;
};
}

int main()
{
#ifdef FOLLY_CPLUSPLUS
folly::fbvector
#else
std::vector
#endif
<int, my_allocator<int> > numbers;
numbers.push_back(1);
return 0;
}

This compiles and runs fine with GCC, Clang, and MSVC (on, say, C++17).

But now try to uncomment the #include so that it uses folly and you suddenly get errors like this:

/usr/include/folly/FBVector.h:148:27: error: no viable conversion from 'folly::fbvector<int, my_allocator<int>>::Impl::pointer' (aka 'my_pointer<int>') to 'int *'
S_destroy_range(b_, e_);
/usr/include/folly/FBVector.h:365:34: note: passing argument to parameter 'first' here
static void S_destroy_range(T* first, T* last) noexcept {

Funny, so S_destroy_range is used internally, and it requires raw pointers. But who says my fancy pointers will even necessarily map 1:1 to a linear (and contiguous!) pointer space?

What we see here is folly pretends to support custom allocators, but it cuts corners internally. (!) Which is awful not only because of the inflexibility, but because it misleads you, too. If they're introducing unfounded assumptions internally just out of sheer convenience, how am I supposed to trust the implementation? Heck, if I had implemented implicit conversions to raw pointers so that the code compiled, I might not have even discovered there's a latent bug in my program.

In contrast, in my experience, actual standard library implementations pay attention to the details and don't tend to cut corners like third party libraries do.

Now, again, keep in mind this is what we get with some of the best libraries, whereas I was talking about the general landscape, so the situation isn't even remotely this good on average.