Constructor overloading with templates

Hi!
I'm trying to overload my constructor and running into errors. My code is working fine with just one constructor but I try to overload it gives me errors:
The header of the working code:

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
49
50
51
52
53
54
55
56
#ifndef CXMLString_H
#define CXMLString_H

#include <iostream>
#include <sstream>
#include "CComplex.h"

using namespace std;

namespace CXML
{

enum XMLParseResult_t
{
	XMLFULLLINE,
	XMLOPENTAG,
	XMLCLOSETAG,
	XMLERRORSYNTAX,
	XMLERRORTAGMISMATCH,
	_XMLMAX
};

template<class T>
class CXMLString: public string
{
private:

	bool extractTag(CXMLString& tag, CXMLString& remainder);
	void trim(string const& temp_compare);
	bool contains(string const sub);
	static string m_error[_XMLMAX];

	/** @link dependency */
	/*# XMLParseResult_t lnkXMLParseResult_t; */
public:
	
	CXMLString(T content, string tag = "")
	{
		stringstream mystream;
		if (tag.length())
			mystream << "<" << tag << ">" << boolalpha << content << "</" << tag
					<< ">";
		else
			mystream << content;
		//str() is used for get/set with the associated string
		string temp = mystream.str();
		assign(mystream.str());
		//*this = "<" + tag + ">" + temp + "</" + tag + ">";
	}


	static string error(XMLParseResult_t);
	XMLParseResult_t parse(string& tag, string& content);
};
}
#endif 


what I want implement is get rid of boolalpha and have another constructor:

1
2
3
4
5
6
7
8
9
CXMLString(bool content, string tag = "")
	 {
	 stringstream mystream;
	 if (content == true)
		 mystream << "<" << tag << ">" << "true" << "</" << tag << ">";
	 else
		 mystream << "<" << tag << ">" << "false" << "</" << tag << ">";
	 assign(mystream.str());
	 }

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
namespace CXML{
	template<>
	CXMLString<bool>::CXMLString(bool content, string tag)
	{
		stringstream mystream;
		if (content)
			mystream << "<" << tag << ">" << "yes" << "</" << tag << ">";
		else
			mystream << "<" << tag << ">" << "no" << "</" << tag << ">";
		assign(mystream.str());
	}
}
Tried this:

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#ifndef CXMLString_H
#define CXMLString_H

#include <iostream>
#include <sstream>
#include "CComplex.h"

using namespace std;

namespace CXML
{

enum XMLParseResult_t
{
	XMLFULLLINE,
	XMLOPENTAG,
	XMLCLOSETAG,
	XMLERRORSYNTAX,
	XMLERRORTAGMISMATCH,
	_XMLMAX
};

template<class T>
class CXMLString: public string
{
private:

	bool extractTag(CXMLString& tag, CXMLString& remainder);
	void trim(string const& temp_compare);
	bool contains(string const sub);
	static string m_error[_XMLMAX];

	/** @link dependency */
	/*# XMLParseResult_t lnkXMLParseResult_t; */
public:

	CXMLString(bool content, string tag = "")
	 {
	 stringstream mystream;
	 if (content == true)
		 mystream << "<" << tag << ">" << "true" << "</" << tag << ">";
	 else
		 mystream << "<" << tag << ">" << "false" << "</" << tag << ">";
	 assign(mystream.str());
	 }


	CXMLString(T content, string tag = "")
	{
		stringstream mystream;
		if (tag.length())
			mystream << "<" << tag << ">" << boolalpha << content << "</" << tag << ">";
		else
			mystream << content;
		string temp = mystream.str();
		assign(mystream.str());
		//*this = "<" + tag + ">" + temp + "</" + tag + ">";
	}


	static string error(XMLParseResult_t);
	XMLParseResult_t parse(string& tag, string& content);
};
}

#endif 


getting the following errors:

1
2
..\myCode\/CXMLStringTemplate.h:48:2: error: 'CXML::CXMLString<T>::CXMLString(T, std::string) [with T = bool, std::string = std::basic_string<char>]' cannot be overloaded
..\myCode\/CXMLStringTemplate.h:37:2: error: with 'CXML::CXMLString<T>::CXMLString(bool, std::string) [with T = bool, std::string = std::basic_string<char>]'
Suppose that you create a CXMLString<bool> both constructor look the same.
Also, it makes no sense to have a constructor with bool for other T

¿why don't you try the code that I posted in response to your request?
Thanks for the code, but I'm getting exactly the same errors as before :(
any suggestions what exactly the problem could be?

This is how I made the changes:
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#ifndef CXMLString_H
#define CXMLString_H

#include <iostream>
#include <sstream>
#include "CComplex.h"

using namespace std;

namespace CXML
{

enum XMLParseResult_t
{
	XMLFULLLINE,
	XMLOPENTAG,
	XMLCLOSETAG,
	XMLERRORSYNTAX,
	XMLERRORTAGMISMATCH,
	_XMLMAX
};

template<class T>
class CXMLString: public string
{
private:

	bool extractTag(CXMLString& tag, CXMLString& remainder);
	void trim(string const& temp_compare);
	bool contains(string const sub);
	static string m_error[_XMLMAX];

	/** @link dependency */
	/*# XMLParseResult_t lnkXMLParseResult_t; */
public:
	CXMLString(bool content, string tag = "");
	CXMLString(T content, string tag = "")
	{
		stringstream mystream;
		if (tag.length())
			mystream << "<" << tag << ">" << boolalpha << content << "</" << tag << ">";
		else
			mystream << content;
		string temp = mystream.str();
		assign(mystream.str());
		//*this = "<" + tag + ">" + temp + "</" + tag + ">";
	}

	static string error(XMLParseResult_t);
	XMLParseResult_t parse(string& tag, string& content);
};
}

namespace CXML{
template<>
CXMLString<bool>::CXMLString(bool content, string tag)
{
	stringstream mystream;
	if (content)
		mystream << "<" << tag << ">" << "yes" << "</" << tag << ">";
	else
		mystream << "<" << tag << ">" << "no" << "</" << tag << ">";
	assign(mystream.str());
}}

#endif 
Last edited on
You are not listening,
`it makes no sense to have a constructor with bool for other T'

Don't write the CXMLString(bool content, string tag = ""); prototype.


Also, ¿why are you including `CComplex.h'?
closed account (o3hC5Di1)
Just to clarify here: ne555 means that it makes no sense to overload the constructor taking a different type, because that's pretty much nullifying the advantage of a template.

What you want to do instead is specialize the template for type bool instead.
Have a google for template specialization, there's no real mystery about it if you understand templates.

Hope that helps.

All the best,
NwN
@ne555 I understand that I really don't need another constructor since all can be done with one I have, but my assignment explicitly tells me to overload the constructor so that's the way I need to do it. Also, now I'm just getting curious as to why it isn't working this way? And i'm including CComplex so that I can create xml not only with strings, ints, floats etc but even complex numbers. Again part of the excercise.

@NwN I read some stuff regarding template specialization and I'm not sure if i have been able to absorb everything since this is actually my first program ever with templates, still to what basic understanding I got I really don't think there is anything wrong with the syntax of what I'm trying to do here.
Last edited on
> I really don't think there is anything wrong with the syntax of what I'm trying to do here.

The problem with the overload is easy to see. With these overloaded constructors,
1
2
3
4
5
template < typename T > struct ambiguous_if_T_is_bool
{
    ambiguous_if_T_is_bool(T) { /*  constructor one - bool */ }
    ambiguous_if_T_is_bool(bool) { /* constructor two - T */ }
};

Think about what would happen if T is bool

1
2
3
4
5
6
7
8
9
10
// fine, constructor one: ambiguous_if_T_is_bool<int>::ambiguous_if_T_is_bool(int)
ambiguous_if_T_is_bool<int> one(45) ;

// fine, constructor two: ambiguous_if_T_is_bool<int>::ambiguous_if_T_is_bool(bool)
ambiguous_if_T_is_bool<int> two(true) ;

// *** error : invalid overload between
// constructor one: ambiguous_if_T_is_bool<int>::ambiguous_if_T_is_bool(bool)
// and constructor two: ambiguous_if_T_is_bool<bool>::ambiguous_if_T_is_bool(bool)
ambiguous_if_T_is_bool<bool> three(true) ;




> this is actually my first program ever with templates
> my assignment explicitly tells me to overload the constructor so that's the way I need to do it.

Who gave you this assignment as a first program ever with templates? And why is such a person trying to teach templates?

An easy way to solve the problem is to take an extra constructor argument (which need not be named or used) in one of the overloaded constructors:
1
2
3
4
5
template < typename T > struct A
{
    A( T, int ) { /* ... */ }
    A( bool ) { /* ... */ }
};


Apparently, that is not what you are allowed to do. A correct solution then would require the use of SFINAE (which is definitely not something that is appropriate for the first template program that a student is writing).

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

template < typename T > struct using_SFINAE
{
    template< typename U > using_SFINAE( typename std::enable_if<
               std::is_same<T,U>::value && !std::is_same<T,bool>::value, T >::type )
    { /* this overloaded constructor one is available only if T is not bool */ }

    using_SFINAE( bool ) { /* overloaded constructor two - bool */ }
};

// fine, constructor one: using_SFINAE<int>::using_SFINAE(int)
using_SFINAE<int> one(25) ;

// fine, constructor two: using_SFINAE<int>::using_SFINAE(bool)
using_SFINAE<int> two(true) ;

// fine, constructor two: using_SFINAE<bool>::using_SFINAE(bool)
// constructor one is not available because T is bool
using_SFINAE<bool> three(true) ;


To clarify what I mean
CXMLString<const char*> foo(false, "tag"); makes no sense.


> now I'm just getting curious as to why it isn't working this way?
told you already.
CXMLString<bool> foo; would generate the code replacing T by bool.
Now look at your class definition
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
class CXMLString<bool>: public string
{
public:
	CXMLString(bool content, string tag = "")
	 {
	 stringstream mystream;
	 if (content == true)
		 mystream << "<" << tag << ">" << "true" << "</" << tag << ">";
	 else
		 mystream << "<" << tag << ">" << "false" << "</" << tag << ">";
	 assign(mystream.str());
	 }


	//CXMLString(T content, string tag = "")
	CXMLString(bool content, string tag = "")
	{
		stringstream mystream;
		if (tag.length())
			mystream << "<" << tag << ">" << boolalpha << content << "</" << tag << ">";
		else
			mystream << content;
		string temp = mystream.str();
		assign(mystream.str());
		//*this = "<" + tag + ">" + temp + "</" + tag + ">";
	}
¿how do you expect the compiler to differentiate the constructors?


> And i'm including CComplex so that I can create xml not only with strings, ints, floats etc but even complex numbers
Include it in main.cpp
Your class is (should be) independent of the template parameter.


> but my assignment explicitly tells me to overload the constructor so that's the way I need to do it.
bad wording, I guess.
To clarify what I mean
CXMLString<const char*> foo(false, "tag"); makes no sense.


> now I'm just getting curious as to why it isn't working this way?
told you already.
CXMLString<bool> foo; would generate the code replacing T by bool.
Now look at your class definition
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
class CXMLString<bool>: public string
{
public:
	CXMLString(bool content, string tag = "")
	 {
	 stringstream mystream;
	 if (content == true)
		 mystream << "<" << tag << ">" << "true" << "</" << tag << ">";
	 else
		 mystream << "<" << tag << ">" << "false" << "</" << tag << ">";
	 assign(mystream.str());
	 }


	//CXMLString(T content, string tag = "")
	CXMLString(bool content, string tag = "")
	{
		stringstream mystream;
		if (tag.length())
			mystream << "<" << tag << ">" << boolalpha << content << "</" << tag << ">";
		else
			mystream << content;
		string temp = mystream.str();
		assign(mystream.str());
		//*this = "<" + tag + ">" + temp + "</" + tag + ">";
	}
¿how do you expect the compiler to differentiate the constructors?


> And i'm including CComplex so that I can create xml not only with strings, ints, floats etc but even complex numbers
Include it in main.cpp
Your class is (should be) independent of the template parameter.


> but my assignment explicitly tells me to overload the constructor so that's the way I need to do it.
bad wording, I guess.
Topic archived. No new replies allowed.