custom allocator adapter

Started by
5 comments, last by CodeCriminal 11 years, 7 months ago
Hi, so as a little excersize I've been looking into c++ allocators a little more and google'd my way to the link below (which I've come across a couple times but never really bothered to dig into it)

http://www.codeproje...n-and-Implement

Something that peaked my interest was the simple memory profiling with the tracking policy class, so I decided to implement something similar to this but instead of using policy classes I went the adapter route. Use of my class goes something like this:

#include "allocator.hpp" // my own allocator header
// ...
std::vector<int, tracking<std::allocator<int>>> vec;
// ...
std::cout << vec.get_allocator( ).total_allocations( ) << std::endl;
// etc. etc..


However this code produces an ungodly amount of errors during compilation, after taking a look it seems that the standard library that comes with gcc at least uses something along the lines of std::allocator_traits<tracking<int>> internally which of course is not what I want.

Is there any way to get around this? I don't understand why int is being passed to tracking in its template parameters, or even how since wouldn't it make more sense to do something like: std::allocator_traits<Allocator>::??? which as far as I can see would work.. I could try the policy based approach but I expect this would fail too unless I have my allocator defined with a default policy or something..

Maybe I will just roll my own containers that mimic the standard. Though as of right now it seems overkill (although fun) just for this tiny error.

Thoughts?
Advertisement

Is there any way to get around this?
[/quote]
Yes. You'll have to share your code so that we can spot the bug. Endeavour to reduce it to the simplest test case possible as it will make it easier to provide advice.


I don't understand why int is being passed to tracking in its template parameters
[/quote]
Neither do we, because we don't have your code :)

because we don't have your code


Ah yes, sorry, I've pasted in codepad simply because I don't like what this forum does to the formatting when you post code.
http://codepad.org/aeiKdVxZ

I thought about trying to add the template parameter Allocator as a template-template parameter, I seem to recall being able to do this but I'm not too well versed in with it so would require some reading on my behalf (though I am doubtful that it will solve my problem).
I don't think your implementation of rebind is correct. I believe it should be something like this:


template <typename T>
struct rebind
{
typedef tracking<typename Allocator::rebind<T>::other> other;
};


I haven't checked the rest, but I suspect that this correction will solve your immediate problem.

I don't think your implementation of rebind is correct. I believe it should be something like this:


template <typename T>
struct rebind
{
typedef tracking<typename Allocator::rebind<T>::other> other;
};


I haven't checked the rest, but I suspect that this correction will solve your immediate problem.


Hmm, that does indeed make sense seeing as the std containers are passing their first template parameter to rebind internally it seems. However it didn't solve my problem and introduced a new error, something along the lines of "template parameter 1 is invalid", and that is just trying to instantiate the template.

I'll take a closer look when I get home (in class right now tongue.png)

EDIT: I just tried a few things out, and one of those things was to inherit from the allocators rebind member which at first spat out some errors during compilation. Then gcc suggested something interesting - 'use Allocator::template rebind to indicate that it is a template' - I have never come across anything like this before but it seems to have fixed the original problem I had with your change to the rebind member when I change it like so:


template <typename T>
struct rebind
{
typedef tracking<typename Allocator::template rebind<T>::other> other;
};


I can already see there are a few other problems with the class that will need to be addressed before I get it working, but when I do I shall report back.

EDIT2: Ok, so I seem to have it working now and the latest draft is pasted below in codepad, it works as expected but I could take this class further providing something a little more feature rich. There wasn't really much that needed to be done to get it working just a few silly mistakes. Thanks for your help smile.png

http://codepad.org/31creIpW

I'm not really sure what to do about the comparison operators, leave them as-is or make comparisons of that data?

EDIT3: Having some troubles with std::list because of the rebinding it does from allocator<int> to allocator<_Node_t<int>*> (or something along those lines...

EDIT: I just tried a few things out, and one of those things was to inherit from the allocators rebind member which at first spat out some errors during compilation. Then gcc suggested something interesting - 'use Allocator::template rebind to indicate that it is a template' - I have never come across anything like this before but it seems to have fixed the original problem I had with your change to the rebind member when I change it like so:

Yes, that construct is required by the language in that situation. Older versions of the Microsoft C+ compiler fail to comply with the language specification on that, I'm not sure about current versions. GCC has required it since 3.0 which was released a decade ago now.

You're poking around with a part of C++ that has all the pointy bits at one end. Hang on, you're in for a fun ride.

BTW, the only place GCC should be using [font=courier new,courier,monospace]std::allocator_traits<tracking<int>>[/font] is in its test suite.

Oh, and one more thing. The current C++ standard changes allocators around a lot. The old C++98 allocator model is being deprecated. It's a good riddance kind of thing.

Stephen M. Webb
Professional Free Software Developer


[quote name='roadysix' timestamp='1348561194' post='4983505']
EDIT: I just tried a few things out, and one of those things was to inherit from the allocators rebind member which at first spat out some errors during compilation. Then gcc suggested something interesting - 'use Allocator::template rebind to indicate that it is a template' - I have never come across anything like this before but it seems to have fixed the original problem I had with your change to the rebind member when I change it like so:

Yes, that construct is required by the language in that situation. Older versions of the Microsoft C+ compiler fail to comply with the language specification on that, I'm not sure about current versions. GCC has required it since 3.0 which was released a decade ago now.
[/quote]

Ah, good to know, I've only been working with gcc for just under a year now (not counting actual time spent programming) and I was a visual studio guy before that, so that's probably the reason why I had never come across it before. (couldn't resist those c++11 features that vc10 was lacking in smile.png )


You're poking around with a part of C++ that has all the pointy bits at one end. Hang on, you're in for a fun ride.


Oh joy a challenge, I look forward to it haha.


BTW, the only place GCC should be using [font=courier new,courier,monospace]std::allocator_traits<tracking<int>>[/font] is in its test suite.


Well since changing the code in the rebind member that edd suggested, that problem has pretty much disappeared, I'm now faced with the getting it to work with std::list. The problem I am getting is that std::list<T, Alloc>::get_allocator( ) or some function there within is trying to call a "supposed" non-existent copy constructor. The errors go a little something like this:

error: no matching function for call to 'type::allocator<std::_List_node<int> >::allocator(const type::allocator<std::_List_node<int> >&)

It works with std::allocator but not my own implementation it seems.. (recently discovered)
...
After one quick look I noticed my constructors where declared explicit, for some reason this blows up in the containers.
Removed the explicit keyword and now everything is working again! .. until I find the next flaw that is.


Oh, and one more thing. The current C++ standard changes allocators around a lot. The old C++98 allocator model is being deprecated. It's a good riddance kind of thing.


Oh really? so am I using the old allocator model? If so where can I find information on constructing allocators that comform to the new standard?

Thanks

[revised code] : http://codepad.org/9mrTYNT2

This topic is closed to new replies.

Advertisement