I'm trying to use a vector to store x and y coordinates of certain data in my vector. I assumed the following would work but that is not the case. I have spent a lot of time searching hoping to get it to work but in vain. I appreciate any help whatsoever.
class A {
public:
A(size_t x, size_t y); //ctor
};
If I want to create a vector of type class A, so 2D, why is
std::vector<A> vec(10); not working?
void count(size_t x, size_t y) {
vec.at(x,y);
}
ERROR: error: no matching function for call to ‘std::vector<Board>::at(size_t, size_t&)
note: candidate expects 1 argument, 2 provided
Since class A's constructor has 2 variables, shouldn#t my vector of type A take 2 variables as well?
If not, what is the correct way of getting a 2d vector of class A such that I can call the .at()-function at x,y and get whatever is stored there?
This vector overload:
std::vector<A> vec(10);
makes 10 copies of type A by calling A's default constructor. Since you didn't provide a default constructor an error occurs. Provide the default constructor:
class A {
public:
A() = default;
};
int main() {
std::vector<A> v(10);
}
or use an appropriate constructor as a second parameter:
class A {
public:
A(size_t x, size_t y) {
// your code
}
};
int main() {
std::vector<A> v(10, A(1, 2));
}
That being said, don't confuse the vector of vectors:
std::vector<std::vector<T>> v;
with a simple constructor taking two parameters or a simple class having two data members.
Related
I write a class using sparse matrices. It happens that for both of them, their non-zeros are on the same (i,j)s. As I have to compute these (i,j)s, I'd prefer to have to do it only once.
Currently, I do it separately and my constructor looks like this:
class C
{
private:
matrix matA;
matrix matA;
holder ijs;
private:
matrix initMatA();
matrix initMatA();
holder init_ijs(int, int);
public:
C(int, int);
};
C::C(int foo, int bar) : init_ijs(foo, bar), matA(initMatA()), matB(initMatB())
{
}
as I've read that it is best practice to use initialization list (and actually, when I first wrote it, if I remember correctly it was impossible to instantiate my matrices otherwise (EDIT: a default constructor seems to fix it?)).
If it was Python, I could write something like
def initMats(foo, bar):
...
return matA, matB
If think the C++ way would be something like
void initMats(int foo, int bar, matrix &matA, matrix &matB)
{
...
}
but I guess I cannot pass reference to objects that have not yet been constructed.
Any clue on a way to solve this? My idea was to first create the (i,j)s list as an attribute to my class so I can later use it in my initA and initB methods, but I will not be needing it afterward I don't think it's the best way to do.
Init methods are not idiomatic in C++. Use constructors.
You can achieve what you want with a delegating constructor (C++11 and newer). First, you need a constructor for the matrix class that accepts an (i,j)-list.
using ijlist = ...; //probably some kind of an array
class matrix {
...
matrix(const ijlist& ijs) { ... }
...
};
Then you write a constructor for C that accepts an ijlist and passes it to the two matrix data members:
class C {
...
matrix matA, matB;
...
C(const ijlist& ijs) : matA(ijs), matB(ijs) { ... }
Now you can compute your (i,j)-list in an auxiliary function and pass it to this constructor from any other constructor:
C() : C(compute_ijs()) { ... }
If I understand the question correctly, you wish to:
take two sparse matricies (or similar) as inputs
compute IJ for the two matricies
apply IJ to them both before continuing
construct the Class with the modified matricies.
The constraint is that the matricies are not default-constructible.
I think I would do it something like this:
// A class to hold the result of computing ij
struct ij_holder
{
// whatever goes here
};
// a sparse matrix class
struct sparse_matrix
{
// let's say it's not default-constructible
sparse_matrix(int, int , int , int);
};
// apply ij to sparse matrix m, returning the modified matrix
sparse_matrix apply(ij_holder const& ij, sparse_matrix m)
{
// whatever goes here to modify m
return m;
}
// compute ij from two matricies
ij_holder compute_ij(sparse_matrix const& a, sparse_matrix const& b);
struct Class
{
// public constructor written in terms of private constructor
Class(sparse_matrix const& foo, sparse_matrix const& bar)
: Class (compute_ij(foo, bar), foo, bar)
{}
private:
// private constructor
Class(ij_holder ij, sparse_matrix const& foo, sparse_matrix const& bar)
: foo_(apply(ij, foo))
, bar_(apply(ij, bar))
{}
sparse_matrix foo_;
sparse_matrix bar_;
};
I want to have class scope alias to the vector from an argument.
For exapmale:
class Solution {
private:
vector<int> b; // I want that &b = a, where a from function solve
int f(int i) {
// here I want to use vector<int> a,
// not passing it as a function argument every time
}
public:
int solve(vector<int>& a) {
// here I want to do smth like b = a; which works for O(1)
}
};
Unfortunatelly, I can't just declare vector<int> &b; , because of the error:
declaration of reference variable 'b' requires an initializer
Could you please, explain how to do it in C++11/14?
Update: I can't change the declaration of int solve(vector<int>& a), the interface provided from outside.
Update: I've changed the code to the more explicit. Looks like I shouldn't do again because in answers and comments people use original variable names. I'm sorry, don't have much experience with StackOverflow.
Maybe this?
class Solution {
public:
vector<int> a;
int maxCoins(const vector<int>& _a) { // const because copying
a.assign( _a.begin(), _a.end() );
}
};
But know that you can also do this if you want a reference to the original vector<int> rather than a copy:
class Solution {
public:
vector<int> & a;
int maxCoins(vector<int>& _a) : a( _a ) {}
};
Update
This is probably closest. You cannot re-initialize a reference, but then this is exactly the use-case for pointers.
class Solution {
public:
vector<int> * a;
int f(int i) {
a->size(); // can access indirectly
(*a)[1]; // element access is slightly trickier
vector<int> & _a = *a; // or can create a direct ref
_a.size();
}
int solve(vector<int>& _a) {
a = &_a; // store address to _a. a reference is like any local variable unless doing something funny
}
};
Update 2 - using no pointers
#include <functional>
class Solution {
public:
// vector<int> a;
typedef vector<int> datatype;
datatype blankref;
std::reference_wrapper<datatype> a = blankref;
int f(int i) {
vector<int> & _a = a;
}
int solve(vector<int>& _a) {
a = std::ref(_a);
}
};
You can't avoid the fact that references are assign-once. References in a class instance have to be assigned using initializer syntax. To have a re-usable reference, you need to have a newly initialized object each time.
To help us here, thanks to advice in comments, there is std::reference_wrapper<T> type that can hold instances of references. It can be assigned to using std::ref( _a ) repeatedly.
Honestly pointers are not inelegant when used right, imo. It comes down to use case and what you believe you would need. Performance wise this probably won't be as good as with pointers (because of temporary objects being constructed), though no guarantees... it should perform similarly in any case.
I have a question, its a bit hard to discribe it so be easy on me please.
I have two classes, A and B, class A have a private member- vector:
class A
{
private:
struct complex
{
int x;
vector< int > y;
};
vector< complex > m_resultVector; // <---- the private member
public:
void getPointerToVector( vector< complex >::iterator it )
{
it = m_resultVector.begin();
}
};
I need to get access (only read) from class B, to this m_resultVector;, I could write a get function but m_resultVector is very long vector and I don't want to copy the entire vector to a new one, I want to send its pointer. also the important part- I need class B cannot change the content of m_resultVector
class B
{
struct complex
{
int x;
vector< int > y;
};
void functionOf_B()
{
A class_A;
vector< complex >::iterator p_resultVector;
class_A.getPointerToVector(p_resultVector); // <------ compilation error here
// some reading from the content of p_resultVector
}
};
when I try to compile it, I get the error:
cannot convert parameter 1 from 'std::_Vector_iterator<_Myvec>' to
'std::_Vector_iterator<_Myvec>'
so basically, I have to questions-
why do I get this error? the complex struct is defined in both classes.
where and how do I need to declare on const iterator on class B, so it will be read only? I'm not sure ...
That is because A::complex and B::complex are different types (with same content, but that does not matter). So that vector<A::complex> and vector<B::complex> are different. Move definition of struct complex outside A and B.
Also there are more issues in your code. A::getPointerToVector does nothing, because it copies input vector iterator to temporary one, assigns a value to it and after return from that function, everything is lost. Using this approach, you would have to pass vector<complex>::iterator as reference (thus vector<complex>::iterator&).
I would rather write a method in A like this
const vector<complex>& get_vector() const
{
return m_resultVector;
}
I this way, you can doo this.
void foo()
{
A class_A;
// do something with A
const vector<complex>& p_result = class_A.get_vector();
// now you are holding whole vector and you can call methods
// defined as const (which does not modify that vector)
p_result.begin();
p_result.at(0);
p_result.end();
}
Zereges solution seems good. But I understand you do not want to return vector. I could not come up with any solution other than below.
In Class A:
void getPointerToVector(int position, int &var,vector<int>& o_Vec)
{
vector<complex>::iterator itr;
complex c;
c = m_resultVector.at(position);
var = c.x;
o_Vec = c.y;
}
In class B :
void functionOf_B()
{
A class_A;
int aVar;
std::vector<int> vec;
class_A.getPointerToVector(2, aVar, vec);
// some reading from the content of p_resultVector
}
I am not sure how efficient and complex this is. I would suggest better to use Zereges solution
I have a c++ generic class that looks like this:
template <class T, int N> class TwoDimArray{
private:
T tda_[N][N];
int n_;
public:
TwoDimArray(T tda[][N]){
..
}
~TwoDimArray(){
..
}
..
}
How would I write a copy constructor that I will be able to call somehow like this:
int a1[][2] = { 1, 2, 3, 4 };
TwoDimArray <int, 2> tdm1(a1);
TwoDimArray tdm1Copy (tmd1); // or whatever the correct form is
I hope I was clear.
You have lots of typos in your code, but declaring a copy constructor is simple:
TwoDimArray(const TwoDimArray& rhs){/*implement it here*/}
The copy constructor is part of a template class, so you must specify the template type when copying
TwoDimArray<int, 2> tdm1Copy (tdm1); // specify <int,2> as the type
or use auto
auto tdm1Copy(tdm2);
Full working example below:
#include <iostream>
template <class T, int N> class TwoDimArray {
private:
T tda_[N][N];
int n_;
public:
TwoDimArray(T tda[][N]) {
// implement
}
~TwoDimArray() {
// implement
}
TwoDimArray(const TwoDimArray& rhs) // don't really need this
{
// implement
}
};
int main()
{
int a1[][2] = { 1, 2, 3, 4 };
TwoDimArray <int, 2> tdm1(a1);
TwoDimArray<int, 2> tdm1Copy (tdm1); // specify <int,2> as the type
}
Unless you are doing this for a homework or learning purposes, just use std::vector<std::vector<T>> to "simulate" a 2-D array.
Additional remark: Since your class contains an array (and not a pointer, they are not the same), you don't need a copy constructor. The default copy constructor does it for you, i.e. copies the array element by element. So, just get rid of the copy constructor altogether and let the compiler generate a default one.
Is there a standard container for a sequence of fixed length, where that length is determined at runtime. Preferrably, I'd like to pass an argument to the constructor of each sequence element, and use that argument to initialize a const member (or a reference). I'd also like to obtain the sequence element at a given index in O(1). It seems to me that all of my requirements cannot be met at the same time.
I know std::array has fixed length, but that length has to be known at compile-time.
std::vector has dynamic size, and allows passing contructor arguments using emplace. Although you can reserve memory to avoid actual reallocations, the type still has to be movable to theoretically allow such reallocations, which e.g. prevents const members.
Then there is std::list and std::forward_list, which don't require a movable type, but which are still resizable and will perform rather poorly under random-access patterns. I also feel that there might be considerable overhead associated with such lists, since each list node will likely be allocated separately.
Strangely enough, std::valarray is my best bet so far, since it has a fixed length and won't resize automatically. Although there is a resize method, your type won't have to be movable unless you actually call that method. The main deficit here is the lack for custom constructor arguments, so initializing const members isn't possible with this approach.
Is there some alternative I missed? Is there some way to adjust one of the standard containers in such a way that it satisfies all of my requirements?
Edit: To give you a more precise idea of what I'm trying to do, see this example:
class A {
void foo(unsigned n);
};
class B {
private:
A* const a;
const unsigned i;
public:
B(A* aa) : a(aa), i(0) { }
B(A* aa, unsigned ii) : a(aa), i(ii) { }
B(const std::pair<A*, unsigned>& args) : B(args.first, args.second) { }
B(const B&) = delete;
B(B&&) = delete;
B& operator=(const B&) = delete;
B& operator=(B&&) = delete;
};
void A::foo(unsigned n) {
// Solution using forward_list should be guaranteed to work
std::forward_list<B> bs_list;
for (unsigned i = n; i != 0; --i)
bs_list.emplace_front(std::make_pair(this, i - 1));
// Solution by Arne Mertz with single ctor argumen
const std::vector<A*> ctor_args1(n, this);
const std::vector<B> bs_vector(ctor_args1.begin(), ctor_args1.end());
// Solution by Arne Mertz using intermediate creator objects
std::vector<std::pair<A*, unsigned>> ctor_args2;
ctor_args2.reserve(n);
for (unsigned i = 0; i != n; ++i)
ctor_args2.push_back(std::make_pair(this, i));
const std::vector<B> bs_vector2(ctor_args2.begin(), ctor_args2.end());
}
Theoretically vector has the properties you need. As you noted, actions that possibly do assignments to the contained type, including especially any sequence modifications (empace_back, push_back, insert etc.) are not supported if the elements are noncopyable and/or nonassignable. So to create a vector of noncopyable elements, you'd have to construct each element during vector construction.
As Steve Jessop points out in his answer, if you define the vector const in the first place you won't even be able to call such modifying actions - and of course the elements remain unchanged as well.
If I understand correctly, you have only a sequence of constructor arguments, not the real object sequence. If it's only one argument and the contained type has a corresponding constructor, things shoule be easy:
struct C
{
const int i_;
C(int i) : i_(i) {}
};
int main()
{
const std::vector<C> theVector { 1, 2, 3, 42 };
}
If the constructor is explicit, you have to make a list first or explicitly construct the objects in the initializer-list:
int main()
{
auto list = { 1, 2, 3, 4 };
const std::vector<C> theVector (std::begin(list), std::end(list));
const std::vector<C> anotherVector { C(1), C(44) };
}
If it's more than just one argument per constructed object, consider a intermediate creator object:
struct C
{
const int i_;
C(int i, int y) : i_(i+y) {}
};
struct CCreator
{
int i; int y;
explicit operator C() { return C(i,y); }
};
int main()
{
const std::vector<CCreator> ctorArgs = { {1,2}, {3,42} };
const std::vector<C> theVector { begin(ctorArgs), end(ctorArgs) };
}
I think const std::vector<T> has the properties you ask for. Its elements aren't actually defined with const, but it provides a const view of them. You can't change the size. You can't call any of the member functions that need T to be movable, so for normal use they won't be instantiated (they would be if you did an extern class declaration, so you can't do that).
If I'm wrong, and you do have trouble because T isn't movable, try a const std::deque<T> instead.
The difficulty is constructing the blighter -- in C++11 you can do this with an initializer list, or in C++03 you can construct a const vector from a non-const vector or from anything else you can get iterators for. This doesn't necessarily mean T needs to be copyable, but there does need to be a type from which it can be constructed (perhaps one you invent for the purpose) .
Add a level of indirection by using a std::shared_ptr. The shared pointer can be copied and assigned as usual, but without modifying the object that is pointed to. This way you should not have any problems, as the following example shows:
class a
{
public:
a(int b) : b(b) { }
// delete assignment operator
a& operator=(a const&) = delete;
private:
// const member
const int b;
};
// main
std::vector<std::shared_ptr<a>> container;
container.reserve(10);
container.push_back(std::make_shared<a>(0));
container.push_back(std::make_shared<a>(1));
container.push_back(std::make_shared<a>(2));
container.push_back(std::make_shared<a>(3));
Another advantage is the function std::make_shared which allows you to create your objects with an arbitrary number of arguments.
Edit:
As remarked by MvG, one can also use std::unique_ptr. Using boost::indirect_iterator the indirection can be removed by copying the elements into a new vector:
void A::foo(unsigned n)
{
std::vector<std::unique_ptr<B>> bs_vector;
bs_vector.reserve(n);
for (unsigned i = 0; i != n; ++i)
{
bs_vector.push_back(std::unique_ptr<B>(new B(this, i)));
}
typedef boost::indirect_iterator<std::vector<std::unique_ptr<B>>::iterator> it;
// needs copy ctor for B
const std::vector<B> bs_vector2(it(bs_vector.begin()), it(bs_vector.end()));
// work with bs_vector2
}
I also encounter this problem, the use case in my code is to provide a thread-safe vector, the elements number is fixed and are atomic numbers. I have read all the great answers here. I think we may also consider my solution:
Just inherited the std::vector and hide the modifiers such as push_back, emplace_back, erase, then we get a fixed size vector. We can only access and modify the elements with operator [].
template <typename T>
class FixedVector : protected std::vector<T> {
public:
using BaseType = std::vector<T>;
FixedVector(size_t n) : BaseType(n) {}
FixedVector(const T &val, size_t n) : BaseType(val, n) {}
typename BaseType::reference operator[](size_t n) {
return BaseType::operator[](n);
}
};