Error when resizing vector of template object - c++

I am trying to create a vector of vector of a template object. The error occurs when I try to resize the inner vector and I can't make heads or tail of the error message. I don't know where it gets the HashTable::Item::Item from. Any suggestions?
/usr/include/c++/4.4.6/bits/stl_vector.h(552): error: no instance of constructor "HashTable::Item::Item [with Key=int, Value=Varvalue]" matches the argument list
resize(size_type __new_size, value_type __x = value_type())
detected during:
instantiation of "void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type={size_t={unsigned long}}, std::vector<_Tp, _Alloc>::value_type) [with _Tp=HashTable<int, Varvalue>::Item, _Alloc=std::allocator<HashTable<int, Varvalue>::Item>]" at line 118 of "main.cc"
Here is the relevant code:
#define VECLEN 16
class Varvalue
{
public:
char data[32];
};
template
class HashTable
{
private:
class Item
{
public:
bool valid;
Key key;
Value value;
Item *next;
Item(const Key k, const Value v, Item *b = 0, bool val = true):
key(k), value(v), next(b), valid(val) {}
};
vector<vector<Item> > table;
int tableSize;
HashTable(const int s): tableSize(s)
{
table.resize(tableSize);
for(int i=0; i<table.size(); i++)
table[i].resize(VECLEN); // <<-- error line 118
}
}
int main()
{
HashTable<int, Varvalue> htable(nkeys);
}

Item doesn't have a default constructor, so you need to provide 2 arguments to resize a vector<Item>. The latter argument shall be a "default" Item with which to fill the vector.

In C++, when you declare a class and you don't provide a constructor a default constructor (without any input parameters) is automatically generated. When you do declare a constructor with input parameters you are not awarded the default constructor. In your case, you did declare a constructor for class item which needs k and v as input parameters but you failed to give them, so either declare a constructor with no input parameters for item or supply k and v.

Related

How to initialize the array-like member variable in the constructor?

How to initialize the array-like member variable?
The visual studio code says:
no matching function for call to 'Node::Node()' gcc line 12 col 9
const int N = 100;
struct Node {
int val, ch[2];
/**
void init(int _val) {
this->val = _val, this->ch[0] = this->ch[1] = 0;
}*/
Node (int _val): val(_val) {
this->ch[0] = this->ch[1] = 0;
}
} tree[N]; // <--------- this is line 12
int main() {
int a;
cin >> a;
tree[0] = Node(a);
}
The problem is that when you wrote tree[N] you're creating an array whose elements will be default constructed but since there is no default constructor for your class Node, we get the mentioned error.
Also, Node doesn't have a default constructor because you've provided a converting constructor Node::Node(int) so that the compiler will not automatically synthesize the default ctor Note::Node().
To solve this you can add a default ctor Node::Node() for your class.

Insert non-default constructed element in std::map

this is probably a damn straightforward question. But I can't seem to insert my object into a map. I'm pretty sure I do not have to define my own copy constructor, as I solely using standard stuff. Feel like banging my head against a wall now :lol:, this is the map I am trying to create:
map<unsigned, Vertex> vertexes;
Header file of Vertex:
#ifndef KNOTSV2_VERTEX_H
#define KNOTSV2_VERTEX_H
#include <forward_list>
#include <set>
#include <iostream>
#include "VertexType.h"
using namespace std;
// Defines.
typedef tuple<edge_list, edge_list, edge_list> neigh_set_entry;
/*
* Matching
*/
struct match_first {
match_first(unsigned value) : value(value) {};
template<class A>
bool operator()(const pair<unsigned, A> &a) {
return a.first == value;
}
private:
unsigned value;
};
class Vertex {
public:
/*
* Constructors
*/
Vertex(unsigned identifier, VertexType *type, unsigned attributes) : identifier(identifier), type(type), values(attributes_vec(attributes)) {};
// Methods ..
private:
/*
* Members
*/
unsigned identifier;
attributes_vec values;
VertexType *type;
vector<pair<unsigned, neigh_set_entry>> neigh_set;
};
Function i am trying to call:
Vertex& Graph::create_vertex(VertexType &type) {
Vertex v(id_enumerator++, &type, type.num_attributes());
return vertexes[id_enumerator] = v;
}
note: in instantiation of member function 'std::__1::map, std::__1::allocator > >::operator[]' requested here
return vertexes[id_enumerator] = v;
^
note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided
class Vertex {
^
note: candidate constructor (the implicit copy constructor) not viable:
note: candidate constructor not viable: requires 3 arguments, but 0 were provided
Vertex(unsigned identifier, VertexType *type, unsigned attributes) : identifier(identifier), type(type), values(attributes_vec(attributes)) {};
So I understand it is due to the fact that it tries to call the 'normal constructor', but I don't want to create getter and setters for the values am passing to the constructor; as they may not be changed. As a second attempt I tried to use map::emplace, but no luck there either. Is there any other option besides creating a normal constructor?
Tried emplace and insert and pairwise construct, no luck either.
Vertex& Graph::create_vertex(VertexType &type) {
//Vertex v();
return vertexes.insert(make_pair(id_enumerator, Vertex(id_enumerator, &type, type.num_attributes()))).first->second;
}
Vertex& Graph::create_vertex(VertexType &type) {
//Vertex v();
return vertexes.emplace(id_enumerator, Vertex(id_enumerator, &type, type.num_attributes())).first->second;
}
Vertex& Graph::create_vertex(VertexType &type) {
//Vertex v();
return vertexes.emplace(piecewise_construct, forward_as_tuple(id_enumerator), forward_as_tuple(id_enumerator, &type, type.num_attributes())).first->second;
}
Read std::map::emplace's documentation:
The constructor of the new element (i.e. std::pair<const Key, T>) is called with exactly the same arguments as supplied to emplace, forwarded via std::forward<Args>(args)....
struct Vertex
{
Vertex(unsigned identifier, int type, unsigned attributes) {}
};
int main()
{
std::map<unsigned, Vertex> vertexes;
// Vertex
// vvvvvvvvvvvvvvvvv
vertexes.emplace(0u, Vertex{0u, 1, 0u});
// ^^
// const unsigned
}
live wandbox example

Vector of class type error

So I am trying to push_back an int to my vector but I keep getting a lot of errors in doing so. I know this would work if I just made my vector into "vector< int >" type but I want to know how to do this with a vector of objects such as what I have below.
What can I do to fix this?
#include <iostream>
#include <vector>
using namespace std;
class ClassName
{
public:
ClassName()
{}
~ClassName()
{}
void AddInt(int num)
{
m_Vector.push_back(num);
}
private:
vector<ClassName> m_Vector;
};
int main()
{
// Create our class an add a few ints
ClassName obj;
obj.AddInt(32);
obj.AddInt(56);
obj.AddInt(21);
return 0;
}
errors that I get:
[Error] no matching function for call to
'std::vector::push_back(int&)'
[Note] void std::vector<_Tp, _Alloc>::push_back(const value_type&)
[with _Tp = ClassName; _Alloc = std::allocator;
std::vector<_Tp, _Alloc>::value_type = ClassName]
As #paddy has pointed out in the comments, you will need a constructor that will implicitly convert to the type for you. You are able to do this by declaring a constructor that takes a single parameter of the type you wish to convert to:
class MyInt
{
public:
MyInt(int i) : number(i) {}
private:
int number;
};
This can be used as follows:
int main()
{
std::vector<MyInt> numbers;
numbers.push_back(1);
numbers.push_back(42);
numbers.push_back(MyInt(4)); // explicit conversion
}
However, the main problem you will face with your current design, even after adding a constructor is that you are declaring an object of type ClassName inside ClassName, which you are unable to do.
The only way to get this to work is to declare a pointer to the type:
int main()
{
std::vector< std::unique_ptr<MyInt> > v;
v.push_back(std::make_unique<MyInt>(42));
}
Which would make your class:
class MyInt
{
public:
MyInt() : n(0) {}
MyInt(int i) : n(i) {}
void AddInt(int i)
{
numbers.push_back(std::make_unique<MyInt>(i));
}
private:
int n;
std::vector< std::unique_ptr<MyInt> > numbers;
};
But that doesn't make sense. I can't see why you'd want class ClassName have a vector of ClassName that store numbers; however, this would work fine if you have a class that held an int (see my previous example of MyInt) and then had an MyIntContainer class, which had the following:
class MyIntContainer
{
public:
void AddInt(int i)
{
numbers.push_back(i);
}
private:
std::vector<MyInt> numbers;
};
Standard library containers must be instantiated with complete types.
So it is not possible for a class to contain a std::vector of itself. The line vector<ClassName> m_Vector causes undefined behaviour (no diagnostic requied).
Your options are:
use a non-standard container that allows incomplete types, e.g. a Boost container
use a vector of a different type you've already defined
use a vector of smart pointers
a different way of doing what you're trying to do
Based on your sample code it seems like you might want vector<int> instead of vector<ClassName>, which would avoid this problem.
Usually it doesn't make semantic sense for a class to contain a container of itself (obviously, most such instances would have to contain an empty container otherwise you'll use infinite memory).

C++ struct constructor

I tried to create my own structure. So I wrote this piece of code.
struct node
{
int val, id;
node(int init_val, int init_id)
{
val = init_val;
id = init_id;
}
};
node t[100];
int main()
{
...
}
I tried to compile my program. But I got an error:
error: no matching function for call to 'node::node()'
note: candidates are:
note: node::node(int, int)
note: candidate expects 2 arguments, 0 provided
note: node::node(const node&)
note: candidate expects 1 argument, 0 provided
node t[100];
will try to initialise the array by calling a default constructor for node. You could either provide a default constructor
node()
{
val = 0;
id = 0;
}
or, rather verbosely, initialise all 100 elements explicitly
node t[100] = {{0,0}, {2,5}, ...}; // repeat for 100 elements
or, since you're using C++, use std::vector instead, appending to it (using push_back) at runtime
std::vector<node> t;
This will fix your error.
struct node
{
int val, id;
node(){};
node(int init_val, int init_id)
{
val = init_val;
id = init_id;
}
};
You should declare default constructor.

Calling constructors for element objects in the constructor of a parent class

QUESTION UPDATED:
I want to do the following in C++:
struct Param {
public:
int len;
int in1;
float in2;
};
Param params;
class Element {
private:
int value1;
float value2;
public:
Element();
Element(int n) {value1 = n; value2 = 0;}
Element(int n1, float n2) {value1 = n1; value2 = n2;}
}
class Parent {
private:
class Element elem;
vector<Element> elemVec;
public:
Parent();
Parent(int n);
}
I wish to write the following constructor such that on calling Parent constructor, the non-default constructors for class elements elem and elemVec also gets called. I have figured out that the constructor for elem needs to be called as follows:
Parent::Parent(int n) : elem(n) {
}
How do I now construct each element of elemVec vector, such that Element(int, float) constructor gets called for each vector element with int and float values picked up from the struct fields params.value1 and params.value2. The size of elemVec needs to be defined by the struct field params.len.
Writing a loop in the constructor body gives unwanted behaviour of the constructed objects.
The following implementation should work. However, it depends on the implicit conversion from int to Element, and is not a general solution.
Parent::Parent(int n, const vector<int> &numVec)
: elem(n),
elemVec(numVec.begin(), numVec.end())
{ }
This solution does what you want:
Parent::Parent(int n, const vector<int>& numVec)
: elem(n)
{
elemVec.reserve(numVec.size());
for (auto num : numVec)
elemVec.emplace_back(num);
}
A default construction of an empty vector is basically free.
The reserve allocates the full memory block needed as a vector(n) constructor would.
emplace_back constructs the items in place as efficiently as is possible.