Multiple containers sharing the same memory resource - c++

In my project, I'm trying to use the std::pmr allocator and monotonic_buffer_resource. I'm using vector in various classes, and I need to use the same resource in all of them. I created a separate free function that returns the resource pointer and used it while declaring the vectors. Here is the code
#include <memory_resource>
#include <vector>
#include <array>
std::pmr::monotonic_buffer_resource *getMemoryResource()
{
static std::array<std::byte, 100000> buffer;
static std::pmr::monotonic_buffer_resource resource{buffer.data(), buffer.size()};
return &resource;
}
struct JsonData
{
std::pmr::vector<int> data{getMemoryResource()};
};
struct XMLData
{
std::pmr::vector<char> data{getMemoryResource()};
};
Is there anything I can do to improve the code, especially getMemoryResource function?

Related

boost::multi_index_container crashes with _com_ptr_t objects

I try to use boost::multi_index_container with _com_ptr_t objects.
Code compiles with no warnings but crashes in runtime.
Standard containers (std::set, map etc) work perfectly with such objects.
Is it possible to use multi_index_container with _com_ptr_t?
Sample code here:
#include "stdafx.h"
#include <boost\multi_index_container.hpp>
#include <boost\multi_index\random_access_index.hpp>
#include <boost\multi_index\global_fun.hpp>
#include <boost\multi_index\ordered_index.hpp>
#import "C:\Windows\SysWOW64\msxml6.dll" exclude("ISequentialStream", "_FILETIME")
using CTest =
boost::multi_index_container<MSXML2::IXMLDOMDocument2Ptr,
boost::multi_index::indexed_by<boost::multi_index::random_access<>>>;
int main()
{
::CoInitialize(nullptr);
CTest tst;
MSXML2::IXMLDOMDocumentPtr doc;
doc.CreateInstance(CLSID_DOMDocument);
tst.push_back(std::move(doc)); <-- crash here
::CoUninitialize();
return 0;
}
I notice that the multi_index_container you've defined holds pointers of type MSXML2::IXMLDOMDocument2Ptr, yet doc is of type MSXML2::IXMLDOMDocumentPtr (without the 2). I'm assuming this is OK, as the problem is really not related to this discrepancy.
Boost.MultiIndex does support move semantics, so you can use std::move as you please.
The actual problem is that _com_ptr_t has a weird, destructive operator& overload returning a pointer to the wrapped interface. This confuses the internal code of Boost.MultiIndex. You can easily bypass this overload as follows:
#include <boost\multi_index_container.hpp>
#include <boost\multi_index\random_access_index.hpp>
#include <boost\multi_index\global_fun.hpp>
#include <boost\multi_index\ordered_index.hpp>
#import "C:\Windows\SysWOW64\msxml6.dll" exclude("ISequentialStream", "_FILETIME")
struct IXMLDOMDocument2Ptr:MSXML2::IXMLDOMDocument2Ptr
{
using MSXML2::IXMLDOMDocument2Ptr::IXMLDOMDocument2Ptr;
IXMLDOMDocument2Ptr* operator&(){return this;}
const IXMLDOMDocument2Ptr* operator&()const{return this;}
};
using CTest =
boost::multi_index_container<IXMLDOMDocument2Ptr,
boost::multi_index::indexed_by<boost::multi_index::random_access<>>>;
int main()
{
::CoInitialize(nullptr);
{
// defined in scope so that destruction happens before CoUninitialize
CTest tst;
MSXML2::IXMLDOMDocumentPtr doc;
doc.CreateInstance(CLSID_DOMDocument);
tst.push_back(std::move(doc));
}
::CoUninitialize();
return 0;
}
Would you mind entering a ticket for this problem at Boost Trac? I can fix the issue internally (by not relying on user-overloadable operator&s) but it's going to take a while till I find the time to do so and I wouldn't like to forget about it.
Postscript
If you have this problem throughout your program, you can automate the fix as follows:
#include <boost\multi_index_container.hpp>
#include <boost\multi_index\random_access_index.hpp>
#include <boost\multi_index\global_fun.hpp>
#include <boost\multi_index\ordered_index.hpp>
#import "C:\Windows\SysWOW64\msxml6.dll" exclude("ISequentialStream", "_FILETIME")
template<typename CComPtr>
struct CFixedAddressofComPtr:CComPtr
{
using CComPtr::CComPtr;
CFixedAddressofComPtr* operator&(){return this;}
const CFixedAddressofComPtr* operator&()const{return this;}
};
template<typename CComPtr,typename TIndexList>
using CComPtrMultiIndexContainer=boost::multi_index_container<
CFixedAddressofComPtr<CComPtr>,
TIndexList
>;
using CTest =
CComPtrMultiIndexContainer<MSXML2::IXMLDOMDocument2Ptr,
boost::multi_index::indexed_by<boost::multi_index::random_access<>>>;
int main()
{
::CoInitialize(nullptr);
{
// declared in scope so that destruction happens before CoUninitialize.
CTest tst;
MSXML2::IXMLDOMDocumentPtr doc;
doc.CreateInstance(CLSID_DOMDocument);
tst.push_back(std::move(doc));
}
::CoUninitialize();
return 0;
}

Boost::Variant and function_types in it: How to put functions into Boost::variant?

Lyrics:
I try to implement a task pool over MPI. So I need some kind of RPC but one that would work between different parts of my program, meaning processor A wants processor B to call function C with argument D. We can not pass pointers to functions between processes like we do with threads, so we need some wrapper container to hold our function pointers at each process instance. All inside one source file\one program... So I started wondering about How to store functional objects with different signature in a container. My API Idea back then was wrong - it is better to define all functions in function pool at that pool construction (at least it shall be much easier to implement). But while implementing I faced next trouble:
Problem:
Such simple code (function_types, mpl::vector, variant):
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <string>
template <class T>
int append(T val)
{
std::cout << "hello";
return 0;
}
int main()
{
boost::variant<boost::function_types::function_type< boost::mpl::vector<int,int> >::type , boost::function_types::function_type< boost::mpl::vector<int,std::string> >::type > a;
return 0;
}
Will not compile falling with:
Error 1 error C2066: cast to function type is illegal c:\program files\boost\include\boost\variant\variant.hpp 1231 1
And looking at source we see:
this code block:
variant()
{
// NOTE TO USER :
// Compile error from here indicates that the first bound
// type is not default-constructible, and so variant cannot
// support its own default-construction.
//
new( storage_.address() ) internal_T0();
indicate_which(0); // zero is the index of the first bounded type
}
So I wonder: How to get around this error?
Also I tried:
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <string>
template <class T>
int append(T val)
{
std::cout << "hello";
return 1;
}
int main()
{
boost::variant< boost::function<int (std::string) >, boost::function<int (int) > > a;
a= &append<int>;
return 0;
}
Which fails with:
Error 1 error C2668: 'boost::detail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node::initialize' : ambiguous call to overloaded function c:\program files\boost\include\boost\variant\variant.hpp 1330
Any Ideas on how to make boost.variant hold functions?
Of course we can play with shared pointers to functors like so:
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <string>
template <class in, class out>
struct s_append
{
out operator()(in val) {
std::cout << "hello";
return out();
}
};
int main()
{
boost::variant<boost::shared_ptr<s_append<int, int> >, boost::shared_ptr< s_append<std::string, int> > > a;
boost::shared_ptr<s_append<int, int> > b(new s_append<int, int> );
a=b;
return 0;
}
and it would compile but resulting API sucks - you have to 1) create functors for all functions you want to use (meaning limit there use of current process scope); 2) use shared_pointers and so I don't really even get how to call functions nested that way (simple first guess (*a)(22); just won't compile =( and API starts to be as bad as we would have using Boost.Any).
Try inserting a dummy type as the first argument of the variant. As the comment you found explains, only the first type in the variant is used for the variant's own default constructor. You could use an empty struct type for this (struct NoFunction {};).
That said, you may have been onto something with the idea to use boost::functions as the types in the variant...they are default-constructible at least. I'm not sure what the other error you had from that approach was caused by, but just wanted to let you know you could pursue that angle more if you can't use the dummy-type workaround I mentioned.

Does std::map<key, data> in C++ support native data types like Structures?

How do I map a key to a native data type like structure?
I wrote this snipped but I couldn't compile it. Do you have any ideas on how to fix it?
#include <map>
#include <iostream>
typedef struct _list
{
int a,b;
}list;
map<int,list> test_map;
int main(void)
{
cout <<"Testing"<< endl;
}
map resides in the std:: namespace. Two possible ways to fix this:
using namespace std;
// ...
map<int, list> test_map;
or
std::map<int, list> test_map;
I prefer the second method, but it's a purely personal choice.
On a related note, there is no real limitation on what you can put in a map, aside from the fact that they must be copyable/assignable, and that the key type must have a < operator (or you can also provide a comparer functor).
EDIT: Seems like <list> is included somewhere, either in <iostream> (unlikely) or <map> (strange but not impossible). A using namespace std will cause std::list to clash with your own struct. The solution: rename your struct, or remove the using namespace and put std:: where it's needed.
Added std where required.
Renamed list to mylist to avoid clash with std::list. Avoid typenames and variable names that clash with common usage.
Now compiles OK in VS2008.
#include <map>
#include <iostream>
typedef struct _list
{
int a,b;
} mylist;
std::map<int,mylist> test_map;
int main(void)
{
std::cout <<"Testing"<< std::endl;
return 0;
}
There's no issue with using your struct in the STL containers provided it's copyable cleanly (copy constructor), assignable (implements operator=) and comparable (implements operator<).
A number of problems here:
You're missing either a using::std or std::map, so the compiler doesn't know what map<int,list> means.
Assuming you have a using namespace std declaration, your typedef list might collide with the STL collection of the same name. Change the name.
Your typedef struct _tag {...} tag; construct is an archaic holdover from the 80's. It is not necesarry, and frankly rather silly. It gets you nothing.
Here's your code fixed:
#include <map>
#include <iostream>
struct MyList
{
int a,b;
};
std::map<int,MyList> test_map;
int main(void)
{
std::cout <<"Testing"<< std::endl;
return 0;
}
map<int, _list> test_map; or don't use list(much better) as a name of structure. (You probably also have
#include <list>
...
using namespace std;
somewhere in your code.
I would try to avoid using codepad at all.
I have done a couple of tests with your code and it seems that
it is adding an implicit (and unwanted) using namespace std --it does not require you to qualify map, cout or endl.
it is (probably) including more standard headers than you might want, including #include <list>.
That means that when the compiler looks at the code it is seeing two list, your version and the one in std. Because of the using directive, both are in scope in the line where you create the map and the compiler is not able to determine which to use.
Two simple things that you can do: change the name of your type for the simple test to something other than list (ouch! the tool forcing your naming choices!) or fully qualify the use:
#include <map>
struct list {
int a,b;
};
std::map< int, ::list > the_map;
// ...
Note that codepad is adding the include by itself and the using directive, so it will also compile:
struct list {
int a,b;
};
map<int,::list> the_map;
But that piece of code is wrong
You seem to be comming from C. Try this:
#include <map>
#include <iostream>
struct list
{
int a,b;
};
std::map<int,list> test_map;
int main(void)
{
std::cout <<"Testing"<< std::endl;
return 0;
}

Boost MultiIndex - objects or pointers (and how to use them?)?

I'm programming an agent-based simulation and have decided that Boost's MultiIndex is probably the most efficient container for my agents. I'm not a professional programmer, and my background is very spotty. I've two questions:
Is it better to have the container contain the agents (of class Host) themselves, or is it more efficient for the container to hold Host *? Hosts will sometimes be deleted from memory (that's my plan, anyway... need to read up on new and delete). Hosts' private variables will get updated occasionally, which I hope to do through the modify function in MultiIndex. There will be no other copies of Hosts in the simulation, i.e., they will not be used in any other containers.
If I use pointers to Hosts, how do I set up the key extraction properly? My code below doesn't compile.
// main.cpp - ATTEMPTED POINTER VERSION
...
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/tokenizer.hpp>
typedef multi_index_container<
Host *,
indexed_by<
// hash by Host::id
hashed_unique< BOOST_MULTI_INDEX_MEM_FUN(Host,int,Host::getID) > // arg errors here
> // end indexed_by
> HostContainer;
...
int main() {
...
HostContainer testHosts;
Host * newHostPtr;
newHostPtr = new Host( t, DOB, idCtr, 0, currentEvents );
testHosts.insert( newHostPtr );
...
}
I can't find a precisely analogous example in the Boost documentation, and my knowledge of C++ syntax is still very weak. The code does appear to work when I replace all the pointer references with the class objects themselves.
As best I can read it, the Boost documentation (see summary table at bottom) implies I should be able to use member functions with pointer elements.
If Host contains lot of data you could use shared_ptr to avoid copying. You could use MultiIndex with shared_ptr in it:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/shared_ptr.hpp>
using namespace boost::multi_index;
struct Host
{
int get_id() const { return id; }
private:
int id;
// more members here
};
typedef multi_index_container<
boost::shared_ptr<Host>, // use pointer instead of real Host
indexed_by<
// hash using function Host::get_id
hashed_unique< const_mem_fun<Host, int, &Host::get_id> >
> // end indexed_by
> HostContainer;
Then you could use it as follows:
int main()
{
HostContainer testHosts;
Host * newHostPtr;
newHostPtr = new Host;
testHosts.insert( boost::shared_ptr<Host>(newHostPtr) );
return 0;
}

Why can't initialize the static member in a class in the body or in the header file?

Could any body offer me any reason about that?
If we do it like that, what's the outcome? Compile error?
The problem is that static initialization isnt just initialization, it is also definition. Take for example:
hacks.h :
class Foo
{
public:
static std::string bar_;
};
std::string Foo::bar_ = "Hello";
std::string GimmeFoo();
main.cpp :
#include <string>
#include <sstream>
#include <iostream>
#include "hacks.h"
using std::string;
using std::ostringstream;
using std::cout;
int main()
{
string s = GimmeFoo();
return 0;
}
foo.cpp :
#include <string>
#include <sstream>
#include <iostream>
#include "hacks.h"
using std::string;
using std::ostringstream;
using std::cout;
string GimmeFoo()
{
Foo foo;
foo;
string s = foo.bar_;
return s;
}
In this case, you can't initialize Foo::bar_ in the header because it will be allocated in every file that #includes hacks.h. So there will be 2 instances of Foo.bar_ in memory - one in main.cpp, and one in foo.cpp.
The solution is to allocate & initialize in just one place:
foo.cpp :
...
std::string Foo::bar_ = "Hello";
...
It is just a limitation in the language it self. Hopefully, when C++0x becomes reality, this limitation would go away.
I think this page gives a somehow good reason:
One of the trickiest ramifications of
using a static data member in a class
is that it must be initialized, just
once, outside the class definition, in
the source file. This is due to the
fact a header file is typically seen
multiple times by the compiler. If the
compiler encountered the
initialization of a variable multiple
times it would be very difficult to
ensure that variables were properly
initialized. Hence, exactly one
initialization of a static is allowed
in the entire program.