I am wondering if I can define a set of stack objects inside as part of list or vector? What I am trying to do is defining a collection of stack objects which I can get and add like normal int or float type inside one of STL containers.
For example: vector<stack> stackCollection But it gives me error:
use of class template 'stack' requires template arguments.
Is there any way to do this in c++?
#include <iostream>
#include <stack>
#include <vector>
#include <list>
using namespace std;
int main() {
vector<stack> stackCollection;
//vector<int> stackCollection;
return 0;
}
You have to specify which type the stack should contain, like this:
vector<stack<int>> stackCollection;
Related
I'm unable to view certain std::map in the watch window. Looking into the .natvis file, there are multiple implementations for std::map. Is there a way to select one or the other?
https://developercommunity.visualstudio.com/content/problem/1056550/im-unable-to-inspect-a-variable-of-type-stdmap-in.html
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <set>
#include <memory>
typedef std::shared_ptr<std::string> PTR_STRING;
typedef std::map<PTR_STRING, std::size_t> accessFunction2Order;
typedef std::set<accessFunction2Order> setOfAccessFunction2Order;
typedef std::map<std::vector<std::size_t>, setOfAccessFunction2Order> A2B;
typedef std::map<PTR_STRING, std::shared_ptr<A2B> > MAP;
int main()
{ MAP s{
{ std::make_shared<std::string>("asdasdasdasdasdasdasdasdasdasd"),
std::make_shared<A2B>()
}
};
const auto &r1 = *s.begin();
}
The map s cannot be watched (something regarding std::_Tree<> being displayed). Curiously a reference to the first element can.
The problem is caused by a (I think hardcoded) limit in the visual studio debugger.
In order to display one variable, the debugger is adapting what he finds in the .natvis file -- but he gives up after some fixed number of attempts to resolve a type.
The solution to this problem is to use something like std::any
(or boost::any for those of us not blessed with being able to use an uptodate C++ version)
to break this STL type into chunks the debugger can deal with.
This is of course only a workaround.
Let's hope that this problem will be solved soon.
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <set>
#include <any>
#include <memory>
typedef std::shared_ptr<std::string> PTR_STRING;
typedef std::map<PTR_STRING, long> accessFunction2Order;
typedef std::set<accessFunction2Order> setOfAccessFunction2Order;
#if 1
typedef std::map<std::vector<std::size_t>, std::any> A2B;
#else
typedef std::map<std::vector<std::size_t>, setOfAccessFunction2Order> A2B;
#endif
typedef std::map<PTR_STRING, std::shared_ptr<A2B> > MAP;
typedef std::shared_ptr<std::size_t> PTR_INT;
int main()
{ const MAP s{
{ std::make_shared<std::string>("asdasdasdasdasdasdasdasdasdasd"),
std::make_shared<A2B>()
}
};
}
l learned "include" keyword are just copy & paste.
But including cpp file makes different compile result.
(gcc6~8 + boost1.69)
// main.cpp
#include <iostream>
// I'll move next code to why.cpp
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/insert_linebreaks.hpp>
#include <boost/archive/iterators/remove_whitespace.hpp>
void testFunc()
{
using namespace boost::archive::iterators;
typedef transform_width<binary_from_base64<remove_whitespace<std::string::const_iterator>>, 8, 6> ItBinaryT;
std::string input;
std::string output(ItBinaryT(input.begin()), ItBinaryT(input.end()));
}
// -----------------------------
int main()
{
return 0;
}
Above code compiled without warning.
But, I replace some code with include cpp..
// main.cpp
#include <iostream>
#include "why.cpp" // <----------
int main()
{
return 0;
}
// why.cpp - just copy&paste
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/insert_linebreaks.hpp>
#include <boost/archive/iterators/remove_whitespace.hpp>
void testFunc()
{
using namespace boost::archive::iterators;
typedef transform_width<binary_from_base64<remove_whitespace<std::string::const_iterator>>, 8, 6> ItBinaryT;
std::string input;
std::string output(ItBinaryT(input.begin()), ItBinaryT(input.end()));
}
It makes warning [-Wsubobject-linkage]
~~ has a field ~~ whose type uses the anonymous namespace
~~ has a base ~~ whose type uses the anonymous namespace
Please look at this link : https://wandbox.org/permlink/bw53IK2ZZP5UWMGk
What makes this difference?
Your compiler treats the main CPP file specially under the assumption that things defined in it are very unlikely to have more than one definition and so some tests for possible violation of the One Definition Rule are not done inside that file. Using #include takes you outside that file.
I would suggest just not using -Wsubobject-linkage since its logic is based on a heuristic that is not applicable to your code.
Constructing multiple objects in shared memory is possible as shown in this example:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <functional>
#include <iostream>
using namespace boost::interprocess;
void construct_objects(managed_shared_memory &managed_shm)
{
managed_shm.construct<int>("Integer")(99);
managed_shm.construct<float>("Float")(3.14);
}
int main()
{
shared_memory_object::remove("Boost");
managed_shared_memory managed_shm{open_or_create, "Boost", 1024};
auto atomic_construct = std::bind(construct_objects,
std::ref(managed_shm));
managed_shm.atomic_func(atomic_construct);
std::cout << *managed_shm.find<int>("Integer").first << '\n';
std::cout << *managed_shm.find<float>("Float").first << '\n';
}
But when I try to create two vectors or a vector and a list, I run into problems with the memory allocation. Is there a way to create multiple containers in a single shared memory in Boost?
I had a look at managed_memory_impl.hpp, but it wasn't of much help either.
This is my code (you have to link it with lib pthread and librt):
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/list.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <cstdlib> //std::system
#include <cstddef>
#include <cassert>
#include <utility>
#include <iostream>
typedef boost::interprocess::allocator<int, boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator; //Define an STL compatible allocator of ints that allocates from the managed_shared_memory. This allocator will allow placing containers in the segment
typedef boost::interprocess::vector<int, ShmemAllocator> MyVector; //Alias a vector that uses the previous STL-like allocator so that allocates its values from the segment
typedef boost::interprocess::allocator<int, boost::interprocess::managed_shared_memory::segment_manager> ShmemListAllocator;
typedef boost::interprocess::list<int, ShmemListAllocator> MyList;
int main(int argc, char *argv[])
{
//Construct managed shared memory
boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, "MySharedMemory", 65536);
//const ShmemAllocator alloc_inst(segment.get_segment_manager());
MyVector *instance = segment.construct<MyVector>("MyType instance")(segment.get_segment_manager());
MyVector *instance2 = segment.construct<MyVector>("MyType instance")(segment.get_segment_manager());
MyList *instance3 = segment.construct<MyList>("MyList instance")(segment.get_segment_manager());
return 0;
}//main
You should either use unique names, or you can use the indexed ("array") style of construction.
See the documentation for the Object construction function family:
//!Allocates and constructs an array of objects of type MyType (throwing version)
//!Each object receives the same parameters (par1, par2, ...)
MyType *ptr = managed_memory_segment.construct<MyType>("Name")[count](par1, par2...);
and
//!Tries to find a previously created object. If not present, allocates and
//!constructs an array of objects of type MyType (throwing version). Each object
//!receives the same parameters (par1, par2, ...)
MyType *ptr = managed_memory_segment.find_or_construct<MyType>("Name")[count](par1, par2...);
and
//!Allocates and constructs an array of objects of type MyType (throwing version)
//!Each object receives parameters returned with the expression (*it1++, *it2++,... )
MyType *ptr = managed_memory_segment.construct_it<MyType>("Name")[count](it1, it2...);
and possibly some more. Look for [count].
(I recommend using unique names for simplicity)
Update
To the comments, here's what I meant with "unique name". I've tested it, and itworks fine:
Live1 On Coliru
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/list.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <cassert>
typedef boost::interprocess::allocator<int, boost::interprocess::managed_shared_memory::segment_manager>
ShmemAllocator; // Define an STL compatible allocator of ints that allocates from the managed_shared_memory. This allocator
// will allow placing containers in the segment
typedef boost::interprocess::vector<int, ShmemAllocator> MyVector; // Alias a vector that uses the previous STL-like allocator so
// that allocates its values from the segment
typedef boost::interprocess::allocator<int, boost::interprocess::managed_shared_memory::segment_manager> ShmemListAllocator;
typedef boost::interprocess::list<int, ShmemListAllocator> MyList;
int main()
{
// Construct managed shared memory
std::remove("/dev/shm/MySharedMemory");
boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, "MySharedMemory", 65536);
// const ShmemAllocator alloc_inst(segment.get_segment_manager());
MyVector *instance = segment.construct<MyVector>("MyType instance 1")(segment.get_segment_manager());
MyVector *instance2 = segment.construct<MyVector>("MyType instance 2")(segment.get_segment_manager());
MyList *instance3 = segment.construct<MyList> ("MyList instance")(segment.get_segment_manager());
assert(instance);
assert(instance2);
assert(instance3);
assert(!std::equal_to<void*>()(instance, instance2));
assert(!std::equal_to<void*>()(instance, instance3));
assert(!std::equal_to<void*>()(instance2, instance3));
}
1 Of course, SHM is not supported on Coliru. However, identical sample using mapped file: Live On Coliru
I am making a C++ program which should be able to list the files from particular directory and save each file name as a string(which will be processed further for conversion). Do I need array of strings? Which functionality should I use. The number of files is not fixed.
Main thing is I can't enter the names manually. I must accept the names from the list generated.
In this case you want to use a vector:
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> file_names;
file_names.push_back("file1.txt");
file_names.push_back("file2.txt");
file_names.push_back("file3.txt");
file_names.push_back("file4.txt");
return 0;
}
Have you thought about using some command line tools to deal with this? Even input redirection will work for this. Example:
./Cpp < echo somedir/*
Where Cpp is the name of your compiled binary, and somedir is the directory you want to read from
Then in your c++ program, you simply use std::cin to read each filename from standard in.
#include <vector>
#include <string>
#include <iterator> // std::istream_iterator, std::back_inserter
#include <algorithm> //std::copy
#include <iostream> // std::cin
int main()
{
std::vector<string> file_names;
// read the filenames from stdin
std::copy(std::istream_iterator<std::string>(std::cin), std::istream_iterator<std::string>(), std::back_inserter(file_names));
// print the filenames
std::copy(file_names.begin(), file_names.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
I encountered a weird problem just now.
The source code is simple and self-evident as follows:
#include <vector>
#include <iostream>
#include <functional>
using namespace std;
using namespace std::tr1;
template<class T_>
void show_size(T_ coll)
{
cout << coll.size();
}
int main()
{
vector<int> coll;
coll.push_back(1);
show_size(ref(coll));
return 0;
}
The VC++ 2010 reports:
error C2039: 'size' : is not a member of 'std::tr1::reference_wrapper<_Ty>'
As we know, reference_wrapper can automatically convert itself to its underlying type, here is vector<int>. Why is such simple code not valid?
No it can't that's the whole point of the reference wrapper, because it doesn't decay from the reference, unless explicitly requested using .get()
Edit: don't mix up the boosts reference wrapper with the standard one, the boost one actually has implicit conversion (but the target functionality is a little bit different)