I have trying to make a clone of adjacency list in c++. But couldn't possibly do so.
I have declared using:
vector<int> adj[N]; // N is the number of vertices
How do I make the clone of this list in c++ ?
I tried looking up on the web. But couldn't find any answer. Requesting my fellow mates to answer this question.
I recommend to avoid using old c style arrays in c++ in favor of only std::vector (or std::array for static sized arrays).
Your adjacency list could be implemented using:
std::vector<std::vector<int>> adj(N);
This is using the std::vector constructor that accepts a size, and enables N to be dynamic (whereas in your code it must be known at compile time because c++ does not support VLAs - variable length arrays).
Cloning is easy:
std::vector<std::vector<int>> clone = adj;
If you must use a c style array, you can clone it with:
vector<int> clone[N];
std::copy(std::begin(adj), std::end(adj), std::begin(clone));
A side note: better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
Related
I woud like to know what is the meanig of "ref" in a vector type definition.
I am new to C++ and on the piece of code I am stripping out to learn I found
vector<ref<StupidBug> > bugs;
where “StupidBug” is a class.
It doesn't compile in gcc/C++11 because "template argument ">" is invalid" but moving the “>” to the left, closer to the previous one still gives the same error
That confuses me and I don't know anymore where is the mistake.
The code is a few years old, could it be bad writing? Does "ref" belong to c++?
Is that a multivector? or a template?
The background info:
The whole is about inserting and moving "bugs" in grid and the vector holds the number of bugs and put them in a certain position.
Here the code, first I have a Stupidbug class
class StupidBug
{
public:
int x();
int y();
// member initialization list
StupidBug(GraphID_t i=-1): cellID(i) {}
void move();
void draw(const eco_string& canvas);
};
And the vector with the "ref" is in another class:
class Model: public Space
{
public:
urand u; //random generator for positions
int tstep; //timestep - updated each time moveBugs is called
int scale; //no. pixels used to represent bugs
vector<ref<StupidBug> > bugs;
addBugs(int nBugs);
void addBugs();
void moveBugs();
void draw(TCL_args args);
};
Thanks for any answer!
Yet another reason to stop using namespace std;
It's the function template std::ref<T>
vector<ref<StupidBug> > can't be compiled because std::vector expect a type (in fact 2 type but the other is defaulted) and you provided a function std::ref<StupidBug>
It's probably that your old project have another ref template and somehow, when compile with C++11, it choose std::ref instead of that template.
I am almost sure that it is a user-defined class similar to smart pointers that was designed to substitute standard class std::auto_ptr that can not be used with the class std::vector.
It is possible that this class uses a reference count of objects.
Now instead of
vector<ref<StupidBug> > bugs;
you can write for example
vector<std::unique_ptr<StupidBug> > bugs;
Pay attention to this record of two '>" symbols
vector<std::unique_ptr<StupidBug> > bugs;
^^^^
It means that the code was compiled according to the C++ 2003 Standard when there were not new smart pointers except std::auto_ptr that can not be used with vectors.
There was a problem in the old C++ Standard relative to std::auto_ptr. As result new smart pointers were introduced in the new C++ Standard like std::unique_ptr or std::shared_ptr that can be used along with std::vector and other standard containers.
This class was used because the code is old and the new Standard was not yet adopted with its new classes or maybe it has functionality that is absent in the Standard or more suitable for some class of tasks.
At that time for example Scott Meyers in his book More Effective C++ was showing how a smart pointer with a reference count can be written. This theme wss popular at that days of the C++ 2003 Standard.:)
It is evident that this has nothing common with the standard function std::ref that also was introduced in the C++ 2011 except its name.:)
When the code was written there was neither standard function std::ref.:)
Just look through the header where the class is defined.:)
Now according to the C++ Standard (D.10 auto_ptr)
The class template auto_ptr is deprecated. [ Note: The class template
unique_ptr (20.7.1) provides a better solution. —end note ]
Thus due to the new smart pointers introduced in the new C++ Standard it seems there is no need any more to use this user-defined class ref.
thanks to your answers I was able to fix the issue.
Actually the code is from 2006 and used the c++03 Standard
ref<StupidBug>
is a template used as a custom smart pointer with some extra fuctions and not the „std::ref“ function. It is defined in a header called „classdesc“
For some reason even if I am not using "using namespace std;" the compiler whats to use the „ref“ function instead of the template.
The workaround for me has been using
classdesc::ref<StupidBug>
being „classdesc“ where the original template lives.
Using the new samart pointers from C++11 ( shared_ptr ) didn't work either because of the extra functions of the original template.
I don't know who was more right if #Vlad from Moscow or #StoryTeller....
It is fully safe to change boost::array to std::array? Can it cause any discrepancies?
Is boost::array better over std::array (performance?)?
std::array<T,N> and boost::array<T,N> are standard layout aggregates containing nothing but an array of T[N].
Their interaction with namespace boost and namespace std may be different (Specifically, ADL will find std functions for std::array, and boost functions for boost::array).
So, if there is a function foo in boost, calling foo(some_array) might work if some_array was from boost, and not if it was from std.
The only container algorithms currently in std are std::begin and std::end (and similar the new ones size empty etc if you include near-future ones). Ranges v3 (or whatever gets published) might add some more.
There are more container algorithms in boost than in std. Some of them might fail to build.
In the worst case, someone could write a function with the same name as a container algorithm in boost, with an argument that can implicitly convert from std::array, and the unqualified call to that function could result in a conversion after you change the variable type, while before it called the boost container algorithm.
Similarly, someone could write code that explicitly checks if a template argument is a boost::array and behave differently if it is.
Both of those are a bit of a stretch.
Finally, std::array has modern noexcept decoration, and boost has a public c_array member you can get at (the name std::array member variables is, I believe, not specified). (via #Potatoswatter). I'd personally expect std::array to have better support going forward, as boost::array mainly existed because std lacked the functionality.
Other than those corner cases, std::array should be a drop-in replacement.
In the following code, the compiler complains as: struct std::array<double,5ul> has no member named 'assign'. Here, it seems possible. Why is it so? (Compiler: g++ 4.8.2)
#include <array>
int main()
{
std::array<double,5> arr;
arr.assign(4.); // error: has no member named 'assign'
return 0;
}
array::assign() is a Visual Studio extension. You are compiling with g++. Check here standard g++ array
As already mentioned, there simply is no assign member to std::array.
The interesting question now becomes why ? After all, the other containers have an assign member method !
I would note that unlike other containers, std::array has a fixed size. If you use std::vector<T>::assign (which would be a close equivalent), the vector is resized appropriately to match the size of the sequence being assigned; with an array, however, that would be impossible:
what would you do if the sequence being assigned is shorter than the array ?
what would you do if the sequence being assigned is longer than the array ?
this would be counter-intuitive, as the question does not arise for the other containers since their size is just adapted on the fly.
For a similar reason, std::array does not have: reserve, capacity, clear, insert, emplace, erase, push/pop (and variants) or resize. All of them suppose a container which size may vary.
That is very simple, as you can see here there is no assign member function for an std array. There is however a member function called fill you should be able to use.
The assign method it is not a member of std::array. The member fill does what the assign did in TR1.
assign was originally part of std::tr1::array (from the TR1) and was changed to be fill circa the C++0x (now C++11) draft n2798 (2008).
This is not really a Microsoft extension, I would imagine that they have probably maintained this method for compatibility with, and support for tr1 implementations in production (the method implementations are exactly the same).
Could you please tell me what is the closest data type in C++ to python list? If there is nothing similar, how would you build it in C++?
If you're looking for standard one-dimensional data structures idiomatic to C++, std::vectors, std::lists, and arrays (or std::arrays) all have features similar to Python lists. Which of those data structure you want to choose depends on your requirements. std::vector is a very reasonable structure to default to if you're just looking to store a collection of items.
These data structures all require that each element is of the same type. Generally in C++ that is what you want. However, if you're specifically looking to store a variety of types in the same structure, there are a few options:
You can store void pointers. You will, however, need some way to figure out the type of each element and cast the pointer to the appropriate type to use each element.
If you have a specific set of types you wish to store, you can declare a union (which you'd generally wrap in a struct along with an enum to indicate the type being stored).
Maybe storing boost::any in a std::vector?
http://www.boost.org/doc/libs/1_54_0/doc/html/boost/any.html
Here is a simple working example. See James comments below too.
#include "../boost_1_54_0/boost/any.hpp"
#include <vector>
#include <string>
#include <iostream>
int main()
{
std::vector<boost::any> myList;
myList.push_back(std::string("Hello"));
myList.push_back(10);
myList.push_back(std::string("World"));
std::string any1 = boost::any_cast<std::string> (myList[0]);
int any2 = boost::any_cast<int> (myList[1]);
std::string any3 = boost::any_cast<std::string> (myList[2]);
std::cout<<any1<<" "<<any2<<" "<<any3<<std::endl;
return 0;
}
Actually no C++ container is equivalent to Python's list, which is partially a result of the very different object models of C++ and Python. In particular, the suggested and upvoted std::list is IMHO not even close to Python's list type, a I'd rather suggest std::vector or maybe std::deque. That said, it isn't clear what exactly it is that you want and how to "build it" strongly depends on what exactly "it" is, i.e. what you expect from the container.
I'd suggest you take a look at the C++ containers std::vector, std::deque and std::list to get an overview. Then look at things like Boost.Any and Boost.Variant that you can combine with them, maybe also one of the smart pointers and Boost.Optional. Finally, check out Boost.Container and Boost.Intrusive. If the unlikely case that none of these provide a suitable approximation, you need to provide a better explanation of what your actual goals are.
There is no real equivalent, and it would be extremely difficult
to provide one. Python and C++ are radically different
languages, and providing one really wouldn't make much sense in
the context of C++. The most important differences are that
everything in Python is dynamically allocated, and is an
"object", and that Python uses duck typing.
FWIW: one very early library (before templates) in C++ did offer
containers of Object*, with derived classes to box int,
double, etc. Actual experience showed very quickly that it
wasn't a good idea. (And I'm curious: does any one else
remember it? And particularly, exactly what it was
called---something with NHS in it, but I can't remember more.)
I am working on a wrapper for std::vector that makes it more like Python's lists named pylistpp. The API is just like Python. Example:
#include <list.hpp>
#include <iostream>
int main()
{
list<int> mylist;
mylist.append(5);
mylist.append(7);
int count = mylist.count(5);
std::cout << count << std::endl;
std::cout << mylist.pop(0) << std::endl;
std::cout << mylist.index(7);
return 0;
}
Old c-style static arrays can be quite bothersome when passed as arguments, or returned as value. For that, the new std::array is quite convenient.
However for multi-array, there is nothing in std:: and the boost::multi_array isn't just statically allocated.
Of course, I could do, say,
std::array<std::array<int,3>,2> my_array;
but I find sligthly long and it corresponds to the inverted built-in declaration
int my_array[2][3];
I am just wondering if there is already some "library" coding such a concept (bi-dimensional or any-dimensional)
(which for the latter, if I am correct, must use some variadic template for typing e.g.
multi_array<int,3,4> A;
multi_array<int,3,5,8> B;
multi_array<int,4,7,8,9,8,3> C; //this one being quite rare though
)
EDIT : sorry about the first post, I didn't test
It might be overkill for your application, but I have worked with the Eigen library and think it's family of Matrix template classes might work for you. An example:
Eigen::Matrix<float, 3, 2> a;
a(1,0) = 1.1;
a(0,1) = 17.5;
EDIT 1: Oops, I don't know for sure if it supports N-dimensional matrices. But for 2-dimensional ones I know it is good.
I think you can use typedefs, either with Eigen or with std::array, to make your types more readable.