I have the following data structure
class FamilyMem
{
public:
string name;
string relation;
};
template<class T>
class Paerson
{
public:
string name;
int age;
vector<T> family;
};
I have a vector defined as the following
vector< Paerson<FamilyMem> > p;
I'm using this library and I want to call a function that uses templates, I'm trying to create my own version of the function but it is not working
// I initialize the vector p by calling this function
initPerson(p);
for(int i=0; i< p.size(); p++)
display(p[i]);
This is the function
template<class U>
struct Displaying< std::vector<U> >
{
typedef std::vector<U> Vector;
static void display(const Vector& v)
{
cerr << "Vector Size " << v.size();
}
}
I want to do something like this
template<class U>
struct Displaying< Paerson<FamilyMem> >
{
static void display(const Paerson<FamilyMem> v)
{
for (int i = 0; i < v.family.size(); i++)
cerr << "name " << v.family.name << " relation " << v.family.relation << "\n";
}
}
For some reason it is still calling the vector version and print the size
When performing template specialization, the proper syntax for your case would be template<> rather than template<class U>.
http://en.cppreference.com/w/cpp/language/template_specialization
Related
I am trying to instantiate my sarray class.
sarray array(10);
But I get an error saying that their is no constructor which has a matching definition.
The constructor is defined in the sarray header file
#ifndef SARRAY_H
#define SARRAY_H
template <class T>
class sarray {
public:
template<class T>sarray(int size);
~sarray();
template<class T> T& operator[](int i);
private:
int size;
T* data;
};
And is implemented in the sarray cpp file:
template<class T> sarray::sarray(int size)
: size(size)
{
if (size > 0) data = new T[size];
else {
cout << "illegal array size = " << size << endl;
exit(1);
}
}
Do I need to specify that I am using templates in the constructor call? The constructor argurments and the call arguments match so I am confused by the error message.
VS Syntax Error Message
C++ argument list for class template is missing
Full Source Code
#include "sarray.h"
#include <iostream>;
using namespace std;
template<class T> sarray::sarray(int size)
: size(size)
{
if (size > 0) data = new T[size];
else {
cout << "illegal array size = " << size << endl;
exit(1);
}
}
sarray::~sarray()
{
delete[] data;
}
template<class T> T& sarray::operator[](int i)
{
if (i < 0 || i >= size) {
cout << "index " << i << " is out of bounds." << endl;
exit(1);
}
return data[i];
}
The template<class T> on top of you class affects the whole class. You do not need to keep adding template<class T> in front of all methods of the class. You do need to do it in the definitions of the methods, when you are writing them outside the class. So your class should become:
template <class T>
class sarray {
public:
sarray(int size);
~sarray();
T& operator[](int i);
private:
int size;
T* data;
};
And then the definitions of the methods would look like:
template<class T> sarray<T>::sarray(int size)
: size(size)
{
if (size > 0) data = new T[size];
else {
cout << "illegal array size = " << size << endl;
exit(1);
}
}
template<class T> sarray<T>::~sarray()
{
delete[] data;
}
template<class T> T& sarray<T>::operator[](int i)
{
if (i < 0 || i >= size) {
cout << "index " << i << " is out of bounds." << endl;
exit(1);
}
return data[i];
}
However, as people have commented, it is not a good idea to define the methods of a template class in a separate .cpp file. You could look around the internet for the full explanation why, as it would be too long for here.
If you still want them to be out of the class' declaration (but still in the same header file) for e.g. better readability, then you could do it the shown way.
I got to know that we can also pass template arguments to choose which function should execute. I found them good alternative to function pointers since function pointers has run time cost but template parameters does not. Also, template parameters can be made inline whereas function pointers are not.
Alright then, this is what I wrote to depict my understanding on it. I came close but missing some minor detail somewhere.
template<class T>
class String {
public:
T str;
String() { std::cout << "Ctor called" << std::endl; }
};
template<class T, class C>
int compare(const String<T> &str1,
const String<T> &str2) {
for (int i = 0; (i < str1.length()) && (i < str2.length()); ++i) {
if (C::eq(str1[i], str2[i])) {
return false;
}
}
return true;
}
template<class T>
class Cmp1 {
static int eq(T a, T b) { std::cout << "Cmp1 called" << std::endl; return a==b; }
};
template<class T>
class Cmp2 {
static int eq(T a, T b) { std::cout << "Cmp2 called" << std::endl; return a!=b; }
};
int main() {
String<std::string> s;
s.str = "Foo";
String<std::string> t;
t.str = "Foo";
compare<String<std::string>, Cmp1<std::string> >(s, t);
// compare(s, t);
}
Details of the code:
I have an class String, which take an parameter and create member function of that type.
I have an compare function, which takes two String& arguments. Comparison function is passed to it.
Cmp1 and Cmp2 are two compare functions.
compare<String<std::string>, Cmp1<std::string> >(s, t);
does not get compile here. I tried some other ways to call but in vain.
Looks like you want something like that:
#include <iostream>
#include <string>
template<class T>
class String {
public:
T str;
String() { std::cout << "Ctor called" << std::endl; }
};
template<class T, class C>
int compare(const String<T> &str1,
const String<T> &str2) {
for (int i = 0; (i < str1.str.length()) && (i < str2.str.length()); ++i) {
if (C::eq(str1.str[i], str2.str[i])) {
return false;
}
}
return true;
}
template<class T>
class Cmp1 {
public:
static int eq(T a, T b) { std::cout << "Cmp1 called" << std::endl; return a==b; }
};
template<class T>
class Cmp2 {
public:
static int eq(T a, T b) { std::cout << "Cmp2 called" << std::endl; return a!=b; }
};
int main() {
String<std::string> s;
s.str = "Foo";
String<std::string> t;
t.str = "Foo";
compare<std::string, Cmp1<char> >(s, t);
// compare(s, t);
}
code
Explanations:
You already have String in definition of compare, you need to just send T which is std::string in your case.
You are trying to go through entire std::string, in compare, so, now your code compiles.
You calling cmp on str[index], that is actually char, so you need to call cmp with char template argument.
Clarification: This question originally came from a challenge I thought of, and isn't connect with programming for real systems.
Suppose I have a class, that I know its' architecture which I can't change, and I don't want to inherit it, but I do want to get access to its' private data and functions. How can I do it?
Suppose my class looks like this one:
class A {
public:
int v = 89;
private:
int a = 5;
virtual void function(int a, int b) {
cout << a << " " << b << endl;
}
};
a while ago stumbled upon a neat template trick to do this on this blog: http://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html
Do NOT use this in any production code, it is just a educational example !!!
it takes basically leverage of the "private" being ignored on some part of template initialization
template<typename Tag>
struct result {
/* export it ... */
typedef typename Tag::type type;
static type ptr;
};
template<typename Tag>
typename result<Tag>::type result<Tag>::ptr;
template<typename Tag, typename Tag::type p>
struct rob : result<Tag> {
/* fill it ... */
struct filler {
filler() { result<Tag>::ptr = p; }
};
static filler filler_obj;
};
template<typename Tag, typename Tag::type p>
typename rob<Tag, p>::filler rob<Tag, p>::filler_obj;
usage: take following struct:
struct A {
private:
void f() {
std::cout << "proof!" << std::endl;
}
};
create your "robber"
struct Af { typedef void(A::*type)(); };
template class rob<Af, &A::f>;
use it:
int main()
{
A a;
(a.*result<Af>::ptr)();
return 0;
}
A less risky hack will be to make your function/class a friend of the class if you are allowed to modify just the header file.
// Add
class HackA;
class A {
public:
// Add
friend class HackA;
int v = 89;
private:
int a = 5;
virtual void function(int a, int b) {
cout << a << " " << b << endl;
}
};
Now you can use:
class HackA {
public:
int number(A const& a) { return a.v; }
int another_number(A const& a) { return a.a; }
void target_function(A& a, int number, int another_one)
{
a.function(number, another_one);
}
};
int main()
{
A a;
HackA hacker
cout << hacker.number(a) << " " << hacker.another_number(a) << endl;
hacker.target_function(a, 9, 3);
return 0;
}
I have a template method inside a template class.
I read that a method can not be specialized without specialize the class before.
But I want to factorize some of theses methods, is it possible ?
Example :
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num> class A {
private:
num n;
public:
template<typename type>
void multiplyBy(); // by 1 if <int> or 1,5 if <float>
}; // A
template<> template<> void A<One>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
template<> template<> void A<One>::multiplyBy<float>() {
std::cout << 1.5*n.number << std::endl;
}
template<> template<> void A<Two>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
template<> template<> void A<Two>::multiplyBy<float>() {
std::cout << 1.5*n.number << std::endl;
}
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
A stackoverflow related question : C++ specialization of template function inside template class
In particular this comment : C++ specialization of template function inside template class
Have I to deduct than there is no way to factorize multiplyBy(), for one for int and an other for float ?
As english is not my natural language maybe I miss something simple, maybe a workaround with partial-specialization.
Edit : put A::n in private to match even better my problem.
You might use tag dispatching:
#include <iostream>
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num>
class A {
public:
num n;
private:
template<typename> struct Tag {};
void multiplyBy(Tag<int>) {
std::cout << 1.0*n.number << std::endl;
}
void multiplyBy(Tag<float>) {
std::cout << 1.5*n.number << std::endl;
}
public:
template<typename type>
void multiplyBy() {
multiplyBy(Tag<type>());
}
};
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
But I want to factorize some of theses methods, is it possible ?
You probably know that you cannot use:
template<> template<> void A<One>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
without specializing A<One>.
You can do something along the lines of:
#include <iostream>
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num, typename type = int> struct MultiplyBy {
static void doit(num n)
{
std::cout << 1.0*n.number << std::endl;
}
};
template<typename num> struct MultiplyBy<num, float> {
static void doit(num n)
{
std::cout << 1.5*n.number << std::endl;
}
};
template<typename num> class A {
public:
num n;
template<typename type>
void multiplyBy()
{
MultiplyBy<num, type>::doit(n);
}
};
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
class IFeature
{
public:
virtual std::string string() = 0;
};
class Feature2D
{
public:
virtual std::string string() { .... }
};
class Feature3D
{
public:
virtual std::string string() { .... }
};
void print(std::vector<IFeature*> & v)
{
for (size_t i=0; i<v.size(); i++)
std::cout << v[i]->string() << std::endl;
}
void main()
{
std::vector<Feature2D*> v2d;
// push...
print(v2d); // compile error
std::vector<Feature3D*> v3d;
// push...
print(v3d); // compile error
}
Any suggestions on how I can obtain this print function? (maybe using another data structure different by std::vector)
Thanks
Use a template.
template<typename T> void print(std::vector<T *> const & v) {
for (size_t i=0; i<v.size(); i++)
std::cout << v[i]->string() << std::endl;
}
Or, use a virtual print member function:
class IFeature
{
public:
virtual std::string string() = 0;
virtual void print(std::ostream & Dest) const = 0;
};
void print(std::vector<IFeature *> const & v) {
for (size_t i=0; i<v.size(); i++) {
v[i]->print(cout);
cout << endl;
}
}
Optionally combine with an operator<<
inline std::ostream & operator<<(std::ostream & Dest, IFeature const & v) {
v.print(Dest);
return Dest;
void print(std::vector<IFeature *> const & v) {
for (size_t i=0; i<v.size(); i++)
std::cout << *(v[i]) << std::endl;
}
Just make the vectors IFeature* -vectors. You can store pointers for inherited classes in them just fine.
std::vector<IFeature*> v2d;
v2d.push_back(new Feature2D());
print(v2d);
No need to use templates. Pointers to the superclass are the way to go when you need to access common virtual functions. This way you can also mix different subclasses inside the same vector:
std::vector<IFeature*> vMixed;
vMixed.push_back(new Feature2D());
vMixed.push_back(new Feature3D());
print(vMixed);
Of course, if you also need pointers for the inherited classes, things get a bit more tricky. One option is to store them elsewhere separately. You can also downcast, but that is not usually recommendable.
For the sake of completeness, I'll add that you can reinterpret_cast the vectors, since all vector share the same binary code.
print(reinterpret_cast<std::vector<IFeature*>&>(v2d));
C++ doesn't have covariance for template parameters, but you can simulate it partly if you know what it does under the hood. I found reinterpret_cast to be also useful to convert vector<T*>& to vector<const T*>& for contravariance.
Granted, this is very ugly.
You can make print itself into a template:
template<typename T>
void print(T const &v)
{
for (size_t i=0; i<v.size(); i++)
std::cout << v[i]->string() << std::endl;
}
Better yet, use iterators, then it'll work on most other standard containers as well:
template<typename T>
void print(T const &v)
{
for (T::const_iterator i = v.begin(); i != v.end(); ++i)
std::cout << (*i)->string() << std::endl;
}
Even better (thanks Pedro), pass the iterators themselves:
template<typename Iter>
void print(Iter begin, Iter end) {
for (Iter i = begin; i != end; ++i)
std::cout << (*i)->string() << std::endl;
}
What you are looking for here is interface covariance, which (as far as I know) is not possible on C++ classes. You need to make print also a Templated function (replace IFeature* with T*).