Creating a simple Conversion class

closed account (jvqpDjzh)
I am trying to understand how templates work, if we are talking about putting them in separated files. I would like to create class with templates, precisely I would like now to create a Conversion class, with the usual <sstream> and its classes.

I have read some post about the topic, and apparently one solution is this:
write the template declaration in a header file, then implement the class in an implementation file (for example .tpp), and include this implementation file at the end of the header.

But this seems almost a infinite loop, of course it isn't: the header file includes the source file and the source file has to include the header file.
When we include one file all the contents are copied (if I am not wrong), so it seems not a good idea, especially if the class is very large.

Can you dudes explain me what you know about how to create a template class and implement its methods in a source file?
Maybe with examples I can delete[] all the doubts from the memory.

Thank you in advance.
Last edited on
tpp is not a source file like cpp. It is an arbitrary file extension, so that the compiler does not treat it like a cpp file.

The point of doing this is to merely extend the header file, but that extension is hidden in another file. Remember that when you include a header, the preprocessor merely pastes the code from the header into the destination.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//funky.h
#ifndef HI
#define HI

template <typename Bar>
void funky(Bar);

#include "funky.tpp"

#endif

//funky.tpp

#include <iostream> //Notice we don't include funky.h

template <typename Bar>
void funky(Bar b)
    {std::cout << b;}


After including, the header file becomes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//funky.h
#ifndef HI
#define HI

template <typename Bar>
void funky(Bar);

#include <iostream>

template <typename Bar>
void funky(Bar b)
    {std::cout << b;}

#endif 


So it is just like we would put the definition in the header file, but this way, we "hide" the implementation.
Last edited on
closed account (jvqpDjzh)
And if we have to declare for example a class, in a header file, which includes an #include <string>, and in the source file that extends this last one is also included the <string>, what would happen? what can we do to solve this?

If we are talking about classes and static methods, how would be the simple solution?

Last edited on
It should not matter even if you have, say:
1
2
3
4
5
6
#include <string>
#include <string>
#include <string>
#include <string>
#include <string>
//... 


That is why we have include guards.

If you are worried about multiple copies of your .tpp code (because for some reason you would need to include them in multiple places), you can wrap their code in include guards as well.
Last edited on
closed account (jvqpDjzh)
Ok.
---------------------------------------------------------------------------------------
That's what I have done:
in the main:
1
2
3
4
	string str = Conversion<double>::NumberToString(20);
	cout << str << endl;
	double num = Conversion<double>::StringToNumber( "2014" );
	cout << num << endl;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
Conversion.h
*/
#pragma once
#include <string>

template <class T>
class Conversion{
	public:
		Conversion();
		static std::string NumberToString(T number);
		static T StringToNumber(const std::string &str);
};

#include "Conversion.tpp" 


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
/*
Conversion.tpp
*/

#pragma once

#include <string>
#include <sstream>
using std::string;
using std::istringstream;
using std::ostringstream;

//converts any number to string
template <typename T>
string Conversion<T>::NumberToString(T number)
{
	ostringstream oss;
	oss << number;
	return oss.str();
}

//converts strings to any number speficied
template <typename T>
T Conversion<T>::StringToNumber(const string &str)
{
	istringstream iss(str);
	T number;
	return (iss >> number)? number : 0;
}

------------------------------------------------------------------------------------
ERROR: Conversion.o: No such file or directory
=>
$(BIN): $(OBJ)
$(CPP) $(LINKOBJ) -o $(BIN) $(LIBS)
Are you only compiling main.cpp? Remember that the code in the tpp file is a header extension, and the header should not be compiled.
Last edited on
closed account (jvqpDjzh)
If that means not to build all the project and just press the compile button, yes.
Your linker shouldn't be looking for Conversion.o anyway... I'm afraid I don't really know what's causing this problem. Sorry.
Topic archived. No new replies allowed.