I've been trying to get this piece of code to work with a template but it won't. I don't know how to get the template to work with a class constructor... Don't understand why this won't work.
Well now it doesn't give errors directly, however I'm now unable to call within a different file. It says that 'save' class has no constructors, and that use of class template requires template argument list also indirect from std::string....
#include "save.h"
using std::cin;
using std::cout;
using std::string;
using std::endl;
int main() {
char yes;
string a = "yes";
save<string> A(a);
cin >> yes;
return 0;
}
See 'Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?' here: https://isocpp.org/wiki/faq/templates
Note that you have choice where to define things. The constructors and the destructor could be defined inside the class definition like you did with the read and write functions, or you could define the read and write functions outside the class definition like you did with the constructors and the destructor.
The OP could have retained his original solution by just explicitly declaring a template in a header file, and leave constructor/destructor definition in source files:
//MY HEADER FILE
#ifndef SAVE_H
#define SAVE_H
#include <fstream>
#include <string>
template <typename special>
class save {
private:
int size;
std::fstream A;
public:
save(std::string txt);
~save();
void read(std::string txt) {
A.open(txt, std::fstream::in);
if (A.fail()) {
A.open(txt, std::fstream::out);
}
A.close();
}
void write(std::string txt, special Z[]) {
size = sizeof(Z) / sizeof(Z[0]);
A.open(txt, std::fstream::out | std::fstream::trunc);
for (unsignedint i = 0; i < size; i++) {
A << Z[i];
}
}
};
// explicit template declaration, (extern instantiation for string and int)
externtemplateclass save<int>;
externtemplateclass save<std::string>;
#endif
save.cc source file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include "save.h"
template<typename special>
save<special>::save(std::string txt)
{
A.open(txt, std::fstream::out);
A.close();
}
template<typename special>
save<special>::~save()
{
}
// explicit template instantiation for int and string
// note that we do this once class definition is well known.
templateclass save<int>;
templateclass save<std::string>;
main.cc
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include "save.h"
#include <iostream>
using std::cin;
using std::cout;
using std::string;
using std::endl;
int main() {
char yes;
string a = "yes";
save<string> A(a);
cin >> yes;
return 0;
}
@codekiddy,
If I understand correctly that will work only for the types explicitly declared, which is fine if you want to limit the types the template class can manage but IMO loses a lot of generalization. Or, of course, explicitly instantiate for every type.
An easy way to separate definition from implementation for templates is to simply #include the implementation at the bottom of the template declaration. Whether this is the best method is subjective.
@naraku
Yes, unfortunately it will work only for types explicitly instantiated.
This approach is most useful in your own projects, in which case you know what you need.
Also the purpose of extern keyword is to reduce compile time, not to hide implementation.