Template class initialization in main - c++

class Q
{
Q(const Q &obj) {} // copy constructor
Q& operator= (const Q& a){} // equal op overload
}
template <class T>
class B{
public : T x;
B<T>(T t) {
// x = t; }
}
int main()
{
Q a(2);
a.init(1,0);
a.init(2,1);
B <Q> aa(a); // this line gives error
}
How to initialize template class with copy constructor? B aa(a); // this line gives error
I want to solve it but I could not.
Error:
no matching function for call to 'Q::Q()'|
candidate: Q::Q(const Q&)|
candidate expects 1 argument, 0 provided|
candidate: Q::Q(int)|
candidate expects 1 argument, 0 provided|

To solve the mentioned error just add a default constructor inside class Q as shown below
class Q
{
Q() //default constructor
{
//some code here if needed
}
//other members as before
};
The default constructor is needed because when your write :
B <Q> aa(a);
then the template paramter T is deduced to be of type Q and since you have
T x;
inside the class template B, it tries to use the default constructor of type T which is nothing but Q in this case , so this is why you need default constructor for Q.
Second note that your copy constructor should have a return statement which it currently do not have.

Related

What happens when value is passed to operator overloader function in C++?

I failed to understand the steps of compilation of this code.
First, where is what is purpose of the default constructor, and why so many objects of type MyClass?
link to sololearn where I saved the code
#include <iostream>
using namespace std;
class MyClass {
public:
int var;
MyClass() { }
MyClass(int a)
: var(a) { }
MyClass operator+(MyClass &obj) {
MyClass res;
res.var= this->var+obj.var;
//'this' is refering to active (obj1)
return res;
}
};
int main() {
MyClass obj1(12), obj2(55);
MyClass res = obj1+obj2;
cout << res.var;
}
//I've not understood, its from a lesson
If you suspect you don't need a piece of code, try compiling without it and you'll know pretty quickly whether your suspicion was correct or not.
When you remove the default constructor in the class you provided here's what happens:
..\Playground\: In member function 'MyClass MyClass::operator+(MyClass&)':
..\Playground\:11:21: error: no matching function for call to 'MyClass::MyClass()'
MyClass res;
^~~
..\Playground\:7:9: note: candidate: MyClass::MyClass(int)
MyClass(int a)
^~~~~~~
..\Playground\:7:9: note: candidate expects 1 argument, 0 provided
..\Playground\:4:7: note: candidate: constexpr MyClass::MyClass(const MyClass&)
class MyClass {
Which is to say the problem is in the +operator implementation at the line MyClass res; . This line creates an instance of the object MyClassusing the default constructor, so there's no way the code snippet your provided works without a default constructor.
The constructor without parameters is for the object that doesn't pass any value, the one that stores the sum of the two operand objects. ---simple---

C++ error received

I have this code:
i receive next error: A::A(int) candidate expect 1 argument, 0 provided but I cannot understand what the problem is.
#include <iostream>
using namespace std;
class A
{
int x;
public:
A(int i):x(i) {}
int get_x() const {return x;}
};
class B:public A
{
int *y;
public:
B(int i):A(i) {y=new int[i]; for(int j=0;j<i;j++) y[j]=1;}
B(B&);
int &operator[] (int i) {return y[i];}
};
B::B(B&a)
{
y=new int[a.get_x()];
for(int i=0;i<a.get_x();i++) y[i]=a[i];
}
ostream& operator<<(ostream& o, B a)
{
for(int i=0;i<a.get_x();i++) o<<a[i];
return o;
}
int main()
{
B b(5);
cout<<b;
return 0;
}
Because A does not have a constructor that takes 0 arguments you need to explicitly call the constructor with arguments provided from any class constructor that inherits from A, which is B in this case.
In your first constructor:
B(int i):A(i) {y=new int[i]; for(int j=0;j<i;j++) y[j]=1;}
You are doing this well by calling A(i).
But in your second constructor:
B::B(B&a)
{
y=new int[a.get_x()];
for(int i=0;i<a.get_x();i++) y[i]=a[i];
}
There is no call to A's constructor and thus you get an error since the compiler doesn't know how to create an A object, you probably meant to do :
B::B(B&a) : A(a.get_x())
{
y=new int[a.get_x()];
for(int i=0;i<a.get_x();i++) y[i]=a[i];
}
Your second B constructor B::B(B&a) implicitly tries to construct the base class A using its default constructor, which is not defined.
You may explicitly call the A(int) constructor, i.e.:
B::B(B&a)
: A(a.get_x())
{
...
The problem is that when you declare an object of type B you also sort need to construct an instance of A.
In B::B(B&a) you do not explicitly call any constructor for A, so the compiler try to call the one with no parameters A::A(), but it fails since it is not declared.
You have to either declare a A::A() in A or explicitly call one of the available constructors in A from B's constructror.
Note that A::A() could be automatically generated by the compiler, and is called default constructor. Read more about it here

template of template without default constructor

I'm trying to write a template class that doesn't have default constructor.
For A<int> works fine, but for A<A<int>> I don't know how to get it to work.
1 #include <iostream>
2 using namespace std;
3
4 template <typename T>
5 class A {
6 T x;
7
8 public:
9 A(T y) { x = y; }
10 };
11
12 int main() {
13 A<int> a(0);
14 A<A<int> > b(A<int>(0));
15
16 return 0;
17 }
Error list from clang
test.cpp:9:5: error: constructor for 'A<A<int> >' must explicitly initialize the member 'x' which does not have a default constructor
A(T y) { x = y; }
^
test.cpp:14:16: note: in instantiation of member function 'A<A<int> >::A' requested here
A<A<int> > b(A<int>(0));
^
test.cpp:6:7: note: member is declared here
T x;
^
test.cpp:5:9: note: 'A<int>' declared here
class A {
^
You are not properly constructing x in the initializer list of the constructor, hence A(T y) must default construct x before invoking operator= to copy assign y to it.
int provides a default constructor, which just let the value uninitialized, but A<int> does not.
Your constructor should be
A(T y) : x(y) { }

Templated class constructor uses wrong overload when in struct

The test is as following:
class NotInit{};
NotInit NOT_INIT;
template<class T>
class Optional{
T value;
bool has_value;
public:
Optional() : value(), has_value(false){}
explicit Optional(NotInit):value(), has_value(false) {}
explicit Optional(T const & val):value(val), has_value(true){}
explicit Optional(Optional<T> const & other) {}
Optional& operator=(Optional<T> const & other){}
Optional& operator=(T const & other){}
};
enum X {
FIRST
};
struct Some {
Optional<X> member;
};
int main(int, char**){
Optional<X> const opt(NOT_INIT);
Some s = {NOT_INIT};
return 0;
}
Clang 3.4 complains:
../st.cpp:31:12: error: no viable conversion from 'NotInit' to 'Optional<X>'
Some s = {NOT_INIT};
^~~~~~~~
1 error generated.
Why does it complain for the struct initialization but ont for the varaiable? Why is it not choosing the constructor with the proper parameter?
What overload is missing so that i can use this to init the struct?
I cannot use boost and i'm not sure this error would not appear if using boost::optional.
You are marking your constructors explicit. Thus when you are trying to initialize your struct Some with a brace-initializer list, you are triggering an implicit conversion...
This is prevented here:
class NotInit;
template <typename T>
class Optional {
// Here => Optional(NotInit) cannot be called implicitly
explicit Optional(NotInit):value(), has_value(false) {}
};
/* ... */
Some s = {NOT_INIT}; // Implicit call to Optional<X>(NotInit): whoops!
If you remove the explicit, you can keep:
Some s = {NOT_INIT};
If you chose not to, then you'll have to instantiate s like this:
Some s = {Optional<X>(NOT_INIT)};
In any case, you'll have to remove the explicit keyword on your copy constructor (which has to perform a copy and not be a "dummy" constructor).
Why? Because once the Optional<X> object is built from NOT_INIT, a copy has to be made to s.member.
Note: You could also provide a move constructor, which would be more appropriate in that case, since the object you get from the conversion of NOT_INITis an rvalue.

Creation of a template object C++

How do I call a template constructor whith objects of another class?
Example:
#include <iostream>
using namespace std;
class RGB{
private:
int _R;
int _G;
int _B;
public:
RGB(int a, int b, int c){
_R=a;
_G=b;
_B=c;
}
};
class Gray{
int _G;
public:
Gray(int x){
_G=x;
}
};
template <class T1, class T2>
class Pixel{
public:
Pixel(T1 i, T2 j, int a, int b){
foo=i;
bar=j;
x=a;
y=b;
}
void setPixel(T1 a, T2 b){
foo=a;
bar=b;
}
void getPixel();
private:
int x;
int y;
T1 foo;
T2 bar;
};
int main(){
Gray g(3);
RGB rgb(4, 5, 6);
Pixel<Gray,RGB> pi(g, rgb, 10,27);
return 0;
}
I can use the constructor of the class only with the default constructors of the two classes Bar1 and Bar2 but not with the two objects of the classes that I have created before(in this case bar1 and bar2).
Errors are:
main.cpp: In instantiation of 'Pixel::Pixel(T1, T2, int, int) [with T1 = Gray; T2 = RGB]':
main.cpp:62:37: required from here
main.cpp:35:37: error: no matching function for call to 'Gray::Gray()'
main.cpp:35:37: note: candidates are:
main.cpp:26:5: note: Gray::Gray(int)
main.cpp:26:5: note: candidate expects 1 argument, 0 provided
main.cpp:23:7: note: Gray::Gray(const Gray&)
main.cpp:23:7: note: candidate expects 1 argument, 0 provided
main.cpp:35:37: error: no matching function for call to 'RGB::RGB()'
main.cpp:35:37: note: candidates are:
main.cpp:16:9: note: RGB::RGB(int, int, int)
main.cpp:16:9: note: candidate expects 3 arguments, 0 provided
main.cpp:9:7: note: RGB::RGB(const RGB&)
main.cpp:9:7: note: candidate expects 1 argument, 0 provided
The errors go away if I add default values to the RGB and Gray constructors.
Sorry for the mess, I'm new here...
You need to learn about initialization lists:
Pixel(T1 i, T2 j, int a, int b) : x(a), y(b), foo(i), bar(j) {
}
foo=i;, etc. in the body of the Pixel constructor is assigning to an already existing object. When your Pixel constructor is called, it trys to call the default constructor for its subobjects, Gray and RGB, however, both those types do not have default constructors generated since you provide a user-defined constructor. The solution is to use initialization lists to initialize the subobjects in your Pixel class.
Also, note that subobjects of the class are constructed in the order they are declared inside the class definition, so you should always initialize them in the same order as they are declared in your constructor initialization list.