Would u explain this code about template and class

L

Lippman.Gan

Sorry for that I can not clarify the type of issue in topic.

Look the code below:

template <class T>
class A
{
public:
class a
{
public:
a(int elem):x(elem){cout<<"a::a()\n";}
~a(){cout<<"a::~a()\n";}
int GetX(){return x;};
private:
int x;
};
A(a _a1):a1(_a1){cout<<"haha"<<endl;}
private:
a a1;
friend bool operator ==(const A<int>& t1,const A<int>& t2)
{
cout<<"operator=="<<endl;
return true;
}

};
int main()
{
A<int> b(10); //This would be OK, why?
if(b==10){cout<<"success\n";} //Why this can not run?
return 0;
}

I see in main()
L1, 10 is an integer it implicitly transfer to class a
L2, 10 is also an integer, but it can not implicitly transfer.
why L1 can do this but L2 can not?
 
A

Alf P. Steinbach

* (e-mail address removed):
Sorry for that I can not clarify the type of issue in topic.

Look the code below:

template <class T>
class A
{
public:
class a
{
public:
a(int elem):x(elem){cout<<"a::a()\n";}
~a(){cout<<"a::~a()\n";}
int GetX(){return x;};
private:
int x;
};
A(a _a1):a1(_a1){cout<<"haha"<<endl;}
private:
a a1;
friend bool operator ==(const A<int>& t1,const A<int>& t2)
{
cout<<"operator=="<<endl;
return true;
}

};
int main()
{
A<int> b(10); //This would be OK, why?
if(b==10){cout<<"success\n";} //Why this can not run?
return 0;
}

I see in main()
L1, 10 is an integer it implicitly transfer to class a
L2, 10 is also an integer, but it can not implicitly transfer.
why L1 can do this but L2 can not?

Top-level issue seems to be the declaration of operator== as private.

I haven't compiled the code, so may be more issues.

Cheers, & hth.,

- Alf
 
A

Alf P. Steinbach

* Alf P. Steinbach:
* (e-mail address removed):

Top-level issue seems to be the declaration of operator== as private.

I haven't compiled the code, so may be more issues.

Uh, wait, I didn't see the "friend" there.

This requires more thinking.

Someone else, not me! (Busy!)

Cheers, & sorry this doesn't help you,

- Alf
 
B

Barry

Sorry for that I can not clarify the type of issue in topic.

Look the code below:

template <class T>
class A
{
public:
class a
{
public:
a(int elem):x(elem){cout<<"a::a()\n";}
~a(){cout<<"a::~a()\n";}
int GetX(){return x;};
private:
int x;
};
A(a _a1):a1(_a1){cout<<"haha"<<endl;}
private:
a a1;
friend bool operator ==(const A<int>& t1,const A<int>& t2)
{
cout<<"operator=="<<endl;
return true;
}

};
int main()
{
A<int> b(10); //This would be OK, why?
if(b==10){cout<<"success\n";} //Why this can not run?
return 0;
}

I see in main()
L1, 10 is an integer it implicitly transfer to class a
L2, 10 is also an integer, but it can not implicitly transfer.
why L1 can do this but L2 can not?

I guess "no implicit type conversion" in a friend function.
 
M

Michal Nazarewicz

(I have modified Lippman's code a bit so that it is a full program which
compiles fine.)

#include <iostream>

template <class T> class A {
public:
class a {
int x;
public:
a(int elem) : x(elem) { std::cout << "a::a()\n"; }
~a() { std::cout << "a::~a()\n"; }
int GetX() const { return x; }
};
A(a _a1) : a1(_a1) { std::cout << "haha\n"; }
int GetX() const { return a1.GetX(); }
private:
a a1;
};

bool operator==(const A<int> &t1, const A<int> &t2) {
std::cout << "operator==\n";
return t1.GetX() == t2.GetX();
}

int main() {
A<int> b(10); //L1: This would be OK, why?
if (b==10) std::cout << "success\n"; //L2: Why this can not run?
return 0;
}

I see in main()
L1, 10 is an integer it implicitly transfer to class a
L2, 10 is also an integer, but it can not implicitly transfer.
why L1 can do this but L2 can not?

I would say that in L1 there is a direct conversion from int to
A<int>::a (ie. A<int>::a::a(int) constructor), whereas in L2 to convert
int into A<int> you need two conversions: first convert int into
A<int>::a and then convert it into A<int>. This may be the reason

AFAIK if you want L1 not to compile you can use "explicit" keyword
before a(int) declaration.
 
D

D. Susman

I guess what is wrong with this code is, in the "==" function you're
trying to implicitly cast an int to type class A. In L1, it is valid
because class a is constructed with an int. Since class A is
constructed with a "class a" variable, implicit conversion request
from int to class A is not sound.
Maybe you anticipated for something like "cascaded implicit type
conversion"? Even if it was implemented as a language feature, this
would lead to being typeless in conversions as hierarchies go deep
which would break down a well typed language.
 
P

Pratik Patel

I guess what is wrong with this code is, in the "==" function you're
trying to implicitly cast an int to type class A. In L1, it is valid
because class a is constructed with an int. Since class A is
constructed with a "class a" variable, implicit conversion request
from int to class A is not sound.
Maybe you anticipated for something like "cascaded implicit type
conversion"? Even if it was implemented as a language feature, this
would lead to being typeless in conversions as hierarchies go deep
which would break down a well typed language.

Hello,

Standard performs only one implicit type conversion. So in order for
this code to work, you need to use one user defined conversion using
public: conversion operator. e.g.
operator int ()
{
return a1.GetX();
}

or to stop this working at the first line, make constructor of class a
*explicit*

--Pratik Patel
 
J

James Kanze

(I have modified Lippman's code a bit so that it is a full program which
compiles fine.)
I would say that in L1 there is a direct conversion from int to
A<int>::a (ie. A<int>::a::a(int) constructor), whereas in L2 to convert
int into A<int> you need two conversions: first convert int into
A<int>::a and then convert it into A<int>. This may be the reason

Exactly. In the case of L1, there is an implicit conversion int
to A<int>::a, and the A<int>::a is used to initialize the
variable. One user defined conversion, so OK. In the case of
L2, we need an A<int>, and it would require two user defined
conversions (int to A<int>::a, then A<int>::a to A<int> to get
there), so it is illegal. Note that:

A<int> b = 10 ;

would be illegal too, since copy initialization requires
converting the initialization expression to the target type
(here said:
AFAIK if you want L1 not to compile you can use "explicit" keyword
before a(int) declaration.

And if he wants L2 to compile, he should add a constructor to A
which takes a T.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top