• Create Account

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

6 replies to this topic

Like
0Likes
Like

Posted 24 September 2012 - 12:50 PM

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?

Edited by roadysix, 24 September 2012 - 01:00 PM.

#2e‍dd  Members   -  Reputation: 2105

Like
1Likes
Like

Posted 24 September 2012 - 01:12 PM

Is there any way to get around this?

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

Neither do we, because we don't have your code

Like
0Likes
Like

Posted 24 September 2012 - 01:24 PM

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.

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).

#4e‍dd  Members   -  Reputation: 2105

Like
0Likes
Like

Posted 24 September 2012 - 05:22 PM

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.

Edited by e‍dd, 24 September 2012 - 05:31 PM.

Like
0Likes
Like

Posted 25 September 2012 - 02:19 AM

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 )

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

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...

Edited by roadysix, 25 September 2012 - 05:44 AM.

#6Bregma  Crossbones+   -  Reputation: 5653

Like
0Likes
Like

Posted 25 September 2012 - 07:04 AM

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 std::allocator_traits<tracking<int>> 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

Like
0Likes
Like

Posted 25 September 2012 - 07:20 AM

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.

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 )

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 std::allocator_traits<tracking<int>> 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