0

I'm trying to reproduce the std::vector container, and I saw that in one of the vector constructor prototype we can give an allocator.

explicit vector (size_type n, const value_type& val = value_type(),const allocator_type& alloc = allocator_type()); 

So two questions came to my mind first, why are we able to give an allocator knowing that we already have the allocator_type member type ? second, what happen if I give a different allocator to the constructor ?

So I've tried this code.

#include <vector> #include <iostream> #include <memory> int main() { std::allocator<bool> alloc; std::vector< std::string > ve(10, "hello", alloc); for (int i = 0; i < 10; i++) std::cout << ve[i] << " | "; std::cout << "\n"; return 0; } 

Giving a bool allocator to construct a std::string vector works fine and valgrind doesn't complain about it.

So I'm wondering if the bool allocator gived to the constructor is really used, and if he's not what's the point to be able to give an allocator that can be different from the allocator_type to the constructor ?

Thanks for reading me.

7
  • 1
    (1) The allocator is defaulted in the std::vector template. (2) The passed allocator is copied and used by the container. Commented Dec 12, 2022 at 17:32
  • 1
    The allocator_type member is set to whatever is specified in the Allocator template argument. This is the type of the allocator. The constructor accepts an instance of that type. If you don't provide an instance, the vector will create one internally by default. So, std::vector<std::string> expects a std::allocator<std::string>, don't give it a std::allocator<bool>. I would not expect this code to compile, but it does, I do not know why. Feel free to step into the code with a debugger and find out why for yourself. Commented Dec 12, 2022 at 17:35
  • Thanks for your answer. I dont really know any debugging things except valgrind could you give me a reference tutorial or documentation for debugging things like this please thanks. Commented Dec 12, 2022 at 17:42
  • "...The behavior is undefined (until C++20)The program is ill-formed (since C++20) if Allocator::value_type is not the same as T...." en.cppreference.com/w/cpp/container/vector Commented Dec 12, 2022 at 17:45
  • @RichardCritten This does not apply to the shown code though, where the two do match. Commented Dec 12, 2022 at 17:56

3 Answers 3

2

The code that you have posted will work with some standard library implementations, and fail to compile with others.

Libstdc++, for example, will take the allocator you pass, and immediately create a new allocator (of the correct type) using rebind.

Libc++, on the other hand, will reject the code with a static_assert message.

Sign up to request clarification or add additional context in comments.

1 Comment

There will be an implicit conversion on the constructor argument regardless. The constructor is not templated on the allocator type.
1

why are we able to give an allocator knowing that we already have the allocator_type member type ?

Same reason any type is different from an instance of that type: state.

It is possible to write stateful allocators, where the specific allocator object passed to a particular container affects how it works (for example, which memory pool it allocates from).

what happen if I give a different allocator to the constructor ?

For your particular case, even before C++20, std::allocator has a non-explicit converting constructor which will construct the correct std::allocator<std::string> from the argument you passed.

Obviously this only works when the allocator type parameter is either std::allocator, or some user-defined allocator with a similar converting constructor.


For clarity, there is also a rebind mechanism specifically to help with changing an allocator<T> parameter to a related allocator<U>.

This is needed for node-based containers like

std::map<Key, Value, Compare, Allocator=std:allocator<std::pair<const Key, Value>>> 

because the map doesn't really allocate pair<const Key,Value>, but some private internal type like map<Key,Value>::__node_impl. Obviously the client can't be expected to pass an allocator of the correct type, because it doesn't know the correct type.

Before C++17 this was a member template, and now it uses std::allocator_traits instead. It doesn't participate at all in your example code, though, because the allocator constructor argument still needs to be the same type as the type parameter, even if that isn't the type eventually used.

Comments

1

The allocator_type member (which is equal to the corresponding template parameter of the std::vector class template) determines the type of the allocator used by the vector. Its value_type member must be equal to the value_type of the vector, otherwise there is no guarantee that the vector will work correctly. But in your example allocator_type is std::allocator<std::string> (from the default template argument), matching the value_type which is std::string.

But that determines only the type of the allocator, not its value. An allocator is allowed to have state, so you can't always use it just knowing its type. (Although that is sufficient in the case of std::allocator, which is stateless.)

The parameter to the constructor takes the value for the allocator to use by the vector (and is defaulted to be default-constructed). It is of the exact same type allocator_type. It is not a different type. If you pass it a different type, then either it will fail to compile or it will implicitly convert to allocator_type. Any specialization of std::allocator can be implicitly converted to any other, which is why it doesn't matter what specialization of std::allocator you pass to the constructor. (For allocators other than std::allocator the conversion only needs to be possible explicitly, not necessarily implicitly.) The constructor is not templated on the allocator type. It has a parameter of type allocator_type exactly.

2 Comments

"Matching the value_type": Assume there is no problem with passing a type to the allocator temple, which precisely refers to a default allocator
@SamGinrich Sorry, but I don't understand your comment. What do you want to say?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.