using overloaded == to compare between both int and char

I'm attempting to use an overloaded bool operator "==" to compare between both int and chars.

in all disclosure:
yes--this is a portion of an assignment which is why I've blocked out the rest of my written code to use an overloaded << (which works just fine). I've also changed some of the variables. I don't want anyone copying my work--I'm trying to learn.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//prototype in class strange

friend bool strange<T>::operator==(strange<T>&, strange<T>);


//template function definition
template<class T>
bool operator==(const strange<T>&, const strange<T>) {
	if (strange<T> == strange<T>) {
		return true;
	}
	else return false;
}

//main is below
  
int main(){
strange<int> x1(13, 12), x2(130, 2);
strange<char> y1('z','t'),y2('z','t');
cout << ((x1 == x2) ? "x1 == x2" : "x1 != x2") << endl;
cout << ((y1 == y2) ? "y1 == y2" : "y1 != y2") << endl;
return 0;
}


I'm using visual studio and I'm receiving a

"error LNK2019: unresolved external symbol "bool __cdecl operator==(class strange<char> &,class strange<char>)" (??8@YA_NAAV?$strange@D@@V0@@Z) referenced in function _main"

error upon compilation.

I'm also getting a
"fatal error LNK1120: 1 unresolved externals"

error upon compilation.

All of the templates, class and functions as well as main are in the same .cpp file.

for the life of me, I cant figure out what the heck is up with my boolean overload template and why its returning garbage.
...and stupid me... my prototype didnt match my definition

1
2

friend bool strange<T>::operator==(strange<T>&, strange<T>)

now reads as
1
2

friend bool strange<T>::operator==(const strange<T>&, const strange<T>)


still doesnt work however.
You haven’t asked anything, so I think everyone here supposes you don’t need any help.
Thank you for having kept us up to date with your coding experiences.

Anyway:
Hint 1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

template <typename T> class Strange {
public:
    Strange(T a_arg, T b_arg) : a{a_arg}, b{b_arg} {}
    T a {},
      b {};
    friend bool operator==(const Strange<T>& one, const Strange<T>& two)
    {
        return (one.a == two.a && one.b == two.b);
    }
};

int main()
{
    Strange<int> x1(13, 12), x2(130, 2);
    Strange<char> y1('z', 't'), y2('z', 't');
    std::cout << (x1 == x2 ? "x1 == x2" : "x1 != x2") << '\n';
    std::cout << (y1 == y2 ? "y1 == y2" : "y1 != y2") << '\n';
    return 0;
}


Hint 2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

template <typename T> class Strange {
public:
    Strange(T a_arg, T b_arg) : a{a_arg}, b{b_arg} {}
    T a {},
      b {};
    template <typename T2>
    friend bool operator==(const Strange<T2>& one, const Strange<T2>& two);
};

template <typename T>
bool operator==(const Strange<T>& one, const Strange<T>& two)
{
    return (one.a == two.a && one.b == two.b);
}

int main()
{
    Strange<int> x1(13, 12), x2(130, 2);
    Strange<char> y1('z', 't'), y2('z', 't');
    std::cout << (x1 == x2 ? "x1 == x2" : "x1 != x2") << '\n';
    std::cout << (y1 == y2 ? "y1 == y2" : "y1 != y2") << '\n';
    return 0;
}


I don't want anyone copying my work
I’ve copied it.
> if (strange<T> == strange<T>)
`strange<T>' is a type, no idea what you're trying to do there.
If you intend to put the parameters' names there, then you'll have infinite recursion (¿how do you compare this two thing? you compare them.)

> friend bool strange<T>::operator==(const strange<T>&, const strange<T>)
> still doesnt work however.
¿same error?
also, ¿why do you copy the second parameter?


> I don't want anyone copying my work--I'm trying to learn.
I don't see how you may learn less just because someone steal your work.
And you may benefit from criticism on the rest of your code.


@Enoizat: in your second example, the class is too promiscuous.
thank you both so far! I'm a newbie... basically got thrust into the middle of C++ from a Java background, albeit from a bit ago and only a newbie at that. Frustrating as I understand the basic concepts, but the syntax is killing me. Im also learning that using Visual Studio as an IDE may not be the best thing.

@Enoizat: Thank you for the sanity checking with my boolean. I looked back at it and it made no damn sense in any manner. I have an incredibly bad habit of getting frustrated and going back and trying to edit my code to "make it work".. obviously this NEVER WORKS... I liken it to a nervous tic of mine and something that I'm working on.

@ne555: Thank you as well. the first comparison statement doesn't make a lick of sense. looking at the main. All I'm trying to do is use the == (overloaded) to output one of the " x1==x2" etc.. options in the "cout << (y1 == y2 ? "y1 == y2" : "y1 != y2")" type of lines dependant upon whether true or false. Given this, what I had does not make any sense whatsoever.

I also agree that just because someone may copy my code, doesn't mean that I may learn less. However it does make it a pain in the butt to prove that I just didnt grab code from all places of the internet. That being said.. Code is posted below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

using namespace std;

template <class T>

class strange
{
public:
	
	strange(T a, T b);
	friend ostream& operator<< <> (ostream& osObject, const strange<T>& sObject);
	friend bool operator==(const strange<T>& one, const strange<T>& two);

private:
	T a;
	T b;
};

template <class T>
strange<T>::strange(T first, T second) {
	a = first;
	b = second;
}

template <class T>

ostream& operator<< (ostream& osObject, const strange<T>& sObject) {
	osObject << sObject.a << ", " << sObject.b;
	return osObject;
}

template <class T>
bool operator==(const strange<T>& one, const strange<T>& two)
{
	return (one.a == two.a && one.b == two.b);
}

int main()
{
	strange<int> x1(13, 12), x2(130, 2);	
	cout << "x1 = " << x1 << endl;
	cout << "x2 = " << x2 << endl;
	cout << "y1 = " << y1 << endl;
	cout << "y2 = " << y2 << endl;
	return 0;
}


everything actually compiles without error as long as I do not uncomment the two lines in the main. As soon as I do I get an "LNK2019: unresolved external symbol "bool __cdecl operator==(class strange<int> const &,class strange<int> const &)" (??8@YA_NABV?$strange@H@@0@Z) referenced in function _main" error. Is this something that is perhaps resident to VS, or is it an actual issue? I've realized that VS tends to throw weird wonky crap out due to the compiler itself v. actual errors. Due to this, sometimes I question if its my code (most likely) or the compiler (microsoft product...so still likely).

I'm feeling that the root of the error lies in referencing templates outside of the class and vice versa... perhaps the "friend" for my boolean isnt so friendly?
Last edited on
Option one: declare the function templates prior to the friend declarations.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// declare typename Template strange
template <typename T> class strange ;

// declare function templates
template <typename T> std::ostream& operator<< ( std::ostream&, const strange<T>& ) ;
template <typename T> bool operator== ( const strange<T>&, const strange<T>& ) ;

template <typename T> class strange {

    public:
        strange( T a, T b ) ;

    private:
        T a;
        T b;

    // declare friends (tempates)
    friend std::ostream& operator<< <> ( std::ostream& stm, const strange<T>& s );
    friend bool operator== <> ( const strange<T>& one, const strange<T>& two );
};

http://coliru.stacked-crooked.com/a/6b77773de62be661

Option two: define inline friends

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <typename T> class strange {

    public:
        strange( T a, T b ) ;

    private:
        T a;
        T b;

    // define friends inline (note: do not use <>. note: these friends are found via ADL)
    friend std::ostream& operator<< ( std::ostream& stm, const strange<T>& s ) 
    { return stm << "strange{ " << s.a << ", " << s.b << " }" ; }
    
    friend bool operator== ( const strange<T>& one, const strange<T>& two ) 
    { return one.a == two.a && one.b == two.b ; }
};

http://coliru.stacked-crooked.com/a/1c96af300880407f

More information:
'Why do I get linker errors when I use template friends?' https://isocpp.org/wiki/faq/templates
ne555 wrote:
@Enoizat: in your second example, the class is too promiscuous.

My ex-wife told me something like that (referring to me) before asking divorce. Then I didn’t need further explanations, but now I must ask you if you please can clarify better your point.

Did you mean it’s bad design, a patent error or a code which can fail in some situations? In which ones?
Thank you for any explanation.
you made operator== a template (T2), and all those template instantiations are friends of your class.
For example, operator==<{char, int, double}> are friends of Strange<std::string> and may access its internals.
ne555, thank you for your help. I’m sorry, but I’m afraid I haven’t understood what’s the problem, yet.
I’ll be very grateful if you could provide me a compilable example of a situation where my code could cause problems, if you can.
Thanks in advance.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <string>

template <typename T>
class Strange {
public:
	Strange(T a_arg, T b_arg) : a{a_arg}, b{b_arg} {}
	template <typename T2>
	friend bool operator==(const Strange<T2> &one, const Strange<T2> &two);

private:
	T a{}, b{};
};

template <typename T>
bool operator==(const Strange<T> &one, const Strange<T> &two) {
	Strange<double> result(one.a, one.b); // no problem here, using the public interface
	result.a -= two.a; // but here we access the internals
	result.b -= two.b;
	// return (one.a == two.a && one.b == two.b);
	return result.a == 0 and result.b == 0;
}

// template specialization for T=int
template <>
bool operator==<int>(const Strange<int> &one, const Strange<int> &two) {
	Strange<std::string> foo("hello", "world");
	foo.a = "hell"; // we shouldn't have access to internals of Strange<string>

	return (one.a == two.a && one.b == two.b);
}

int main() {
	Strange<int> x1(13, 12), x2(130, 2);
	Strange<char> y1('z', 't'), y2('z', 't');
	std::cout << (x1 == x2 ? "x1 == x2" : "x1 != x2") << '\n';
	std::cout << (y1 == y2 ? "y1 == y2" : "y1 != y2") << '\n';
	return 0;
}
Thanks a lot for the time you spent to help me understand this issue, ne555.
I’m not surprised I couldn’t guess what you were trying to tell me, since I’ve never entertain the idea of defining an instance of a template of type y inside the x specialisation of the same template.
Anyway, the purpose of friendship is actually to provide access to a class internal state, so, from my limited and inexperienced point of view, a programmer should not be taken by surprise if it happens. But I’ll try to remember your example and avoid that code.
With the class Strange as written, talking about promiscuity (accessing internal state) is mere sophistry.

The class has no identifiable invariant; now and for ever. Every member is public (as it should be, if there are no invariants to be preserved, a la std::pair<>); any code, friend or no friend, can access all of its state.
Topic archived. No new replies allowed.