Operator= doesn't work with std::vector c++ [duplicate] - c++

This question already has answers here:
std::vector::resize() vs. std::vector::reserve()
(5 answers)
Closed 7 years ago.
I have a class
template <class T>
class General_matrix : public Math_object<T>
{
public:
General_matrix(const size_t m, const size_t n);
~General_matrix();
void init();
void show();
T* operator()(const size_t, const size_t) const;
General_matrix<T> operator*(const General_matrix<T>&);
};
derived from
template <class T>
class Math_object
{
protected:
size_t size_m, size_n;
std::vector <T> field;
public:
Math_object(const size_t m, const size_t n);
virtual ~Math_object() = 0;
virtual void show() = 0;
virtual void init() = 0;
};
Operator * doesn't work properly. The building of auxiliary matrix within an operator is OK, but when it comes to returning it changes only the integer data fields in receiving matrix. It turned out that the problem is with operator= for std::vector. I don't want to override it. Has anyone else faced this problem? Why can't I assign vector to vector of the same size?
template <typename T>
General_matrix<T> General_matrix<T>::operator*(const General_matrix<T> &right_operand)
{
General_matrix<T> aux(this->size_m, right_operand.size_n);
T collector;
for (int i=0; i<this->size_m; i++)
{
for (int j=0; j<right_operand.size_n; j++)
{
collector = 0;
for (int k=0; k<this->size_n; k++)
{
collector += *((*this)(i,k)) * *(right_operand(k,j));
}
*(aux(i,j)) = collector;
}
}
return aux;
}
UPD: Here is a MCVE
There are 2 matrices with values {{0,1,2},{3,4,5}} and {{0,1},{2,3},{4,5}}. The result of their multiplication must be {{10,13},{28,40}} and it is {{0,0},{0,0}}.
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class Math_object
{
protected:
size_t size_m, size_n;
std::vector <T> field;
public:
Math_object(const size_t m, const size_t n);
virtual ~Math_object() = 0;
virtual void show() = 0;
virtual void init() = 0;
};
template <class T>
class General_matrix : public Math_object<T>
{
public:
General_matrix(const size_t m, const size_t n);
~General_matrix();
void init();
void show();
T* operator()(const size_t, const size_t) const;
General_matrix<T> operator*(const General_matrix<T>&);
};
template <typename T>
Math_object<T>::Math_object(const size_t m, const size_t n/*=1*/)
{
cout << "Constructor MO"<<"\n";
size_m=m;
size_n=n;
field.reserve(m*n);
}
template <typename T>
Math_object<T>::~Math_object()
{
cout << "Destructor MO"<<"\n";
vector<T>().swap(this->field);
}
template <typename T>
void Math_object<T>::show() {};
template <typename T>
General_matrix<T>::General_matrix(const size_t m, const size_t n):Math_object<T>(m,n)
{
cout << "Constructor GM"<<"\n";
}
template <typename T>
General_matrix<T>::~General_matrix()
{
cout << "Destructor GM"<<"\n";
}
template <typename T>
void General_matrix<T>::init()
{
cout << "Input matrix"<<"\n";
for (int i=0; i<this->size_m*this->size_n; i++)
this->field[i] = i;
}
template <typename T>
T* General_matrix<T>::operator()(const size_t i, const size_t j) const
{
return const_cast<T*>(&(this->field[i*(this->size_n)+j]));
}
template <typename T>
void General_matrix<T>::show()
{
for (int i=0; i < this->size_m; i++)
{
for (int j=0; j < this->size_n; j++)
{
cout << *((*this)(i,j)) << " ";
}
cout << "\n";
}
}
template <typename T>
General_matrix<T> General_matrix<T>::operator*(const General_matrix<T> &right_operand)
{
General_matrix<T> aux(this->size_m, right_operand.size_n);
T collector;
for (int i=0; i<this->size_m; i++)
{
for (int j=0; j<right_operand.size_n; j++)
{
collector = 0;
for (int k=0; k<this->size_n; k++)
{
collector += *((*this)(i,k)) * *(right_operand(k,j));
}
*(aux(i,j)) = collector;
}
}
return aux;
}
template class Math_object<int>;
template class Math_object<float>;
template class General_matrix<int>;
template class General_matrix<float>;
int main()
{
General_matrix<int> k(2,3);
k.init();
General_matrix<int> p(3,2);
p.init();
General_matrix<int> t(2,2);
t=k*p;
t.show();
return 0;
}

One problem, as mentioned in the comments, is the use of reserve instead of resize in the constructor.
But you have also undefined behavior in operator(). Better implement a const and a non-const version.

Related

How to fix "use of class template requires template argument list"

i made some code about stack using template.
but right now, stuck with the little error.
i tried many times as i can but don't know what to do.
also, i see the a lot of same error question but my one is seems to be different.
I'm middle of the writing.
so, there is some uncompleted code.
if you see something wrong but not cause the error, ignore it please.
#ifndef STACKINTERFACE_H
#define STACKINTERFACE_H
using namespace std;
template <typename T>
class StackInterface {
public:
StackInterface() {};
virtual ~StackInterface() {};
virtual bool isEmpty() const = 0;
virtual bool isFull() const = 0;
virtual void push(T data) = 0;
virtual void pop() = 0;
virtual T top() const = 0;
};
#include "StackInterface.h"
#include <iostream>
template <typename T>
class Stack : public StackInterface {
private:
T * items;
const static int max = 10;
const static int GROWBY = 5;
size_t arrayCapacity;
size_t numItems;
int top_position;
public:
Stack();
virtual void push(T data);
virtual T top() const;
virtual void pop();
virtual bool isEmpty() const;
virtual bool isFull() const;
size_t getArrayCapacity();
size_t getNumItems();
Stack<T> operator=(const Stack<T>&Other);
~Stack();
Stack(const Stack<T>& other);
};
template <typename T>
Stack<T>::Stack()
{
items = new T[max];
numItems = 0;
top_position = -1;
}
template <typename T>
Stack<T>::~Stack() {
cout << "deleting..." << endl;
delete[] items;
}
template <typename T>
void Stack<T>::push(T data) {
cout << "inserting" << data << endl;
if (numItems < arrayCapacity) {
T[++top_position] = data;
}
numItems++;
}
template <typename T>
void Stack<T>::pop() {
if (isEmpty) {
cout << "The stack is empty. Returned value not reliable.\n";
}
else {
cout << "removing" << top() << endl;
retrun T[top_position--];
}
}
template <typename T>
bool Stack<T>::isEmpty() const
{
if (numItems == 0) {
return true;
}
else {
return false;
}
}
template <typename T>
bool Stack<T>::isFull() const
{
if (numItems == max) {
return true;
}
else {
return false;
}
}
template <typename T>
T Stack<T>::top() const
{
if (!isEmpty()) {
return T[top_position];
}
else {
throw exception;
}
}
template <typename T>
Stack <T> Stack<T>:: operator=(const Stack<T>&Other) {
if (&Other == this) {
return *this;
}
}
template <typename T>
Stack<T>::Stack(const Stack<T>& other) {
items = new items(other.items);
numItems = other.numItems;
top_position = other.top_position;
arrayCapacity = other.arrayCapacity;
}
template <typename T>
size_t Stack<T>::getArrayCapacity() {
return arrayCapacity;
}
template <typename T>
size_t Stack<T>::getNumItems() {
return numItems;
}
int main() {
Stack <int> S1;
system("pause");
return 0;
}
You need to give template arguments to your superclass. Instead of this:
template <typename T>
class Stack : public StackInterface {
Do this:
template <typename T>
class Stack : public StackInterface<T> {
(There's lots of other problems with your code too, but that's how you fix the specific one you asked about.)

Getting 3 link errors when trying to compile my program [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 5 years ago.
I am creating my own stack and queues by using vectors, lists and dynamic arrays.
I have the following header files for my stack and queue:
miniStack.h
#ifndef MINISTACK_H
#define MINISTACK_H
#include <vector>
#include <list>
using namespace std;
template <typename T>
class miniStackVT {
private:
vector<T> content;
int elementCount;
public:
miniStackVT();
~miniStackVT();
int size() const;
bool IsEmpty() const;
void Push(const T& item);
void PrintStack();
void Pop();
T& TopStack();
};
template <typename T>
class miniStackLT {
private:
list<T> content;
int elementCount;
public:
miniStackLT();
~miniStackLT();
int size() const;
bool IsEmpty() const;
void Push(const T& item);
void PrintStack();
void Pop();
T& TopStack();
};
template <typename T>
class miniStackDA {
private:
T* content;
int elementCount;
void reserve(int n, bool copy);
int arrSize;
public:
miniStackDA();
~miniStackDA();
int size();
bool IsEmpty();
void Push(const T& item);
void PrintStack();
void Pop();
T& TopStack();
};
#endif
miniQueue.h
#ifndef MINIQUEUE_H
#define MINIQUEUE_H
#include <vector>
#include <list>
using namespace std;
template <typename T>
class miniQueueVT {
private:
vector<T> content;
int elementCount;
public:
miniQueueVT();
~miniQueueVT();
void enqueue(const T&);
void dequeue();
T& front();
void PrintQueue() const;
bool IsEmpty();
int size();
};
template <typename T>
class miniQueueLT {
private:
list<T> content;
int elementCount;
public:
miniQueueLT();
~miniQueueLT();
void enqueue(const T&);
void dequeue();
T& front();
void PrintQueue();
bool IsEmpty();
int size();
};
template <typename T>
class miniQueueDA {
private:
T *content;
int elementCount;
void reserve(int n, bool copy);
int arrSize;
public:
miniQueueDA();
~miniQueueDA();
void enqueue(const T&);
void dequeue();
T& front();
void PrintQueue();
bool IsEmpty();
int size();
};
#endif
Here are my .cpp files related to both of my header files:
miniStack.cpp:
#include "miniStack.h"
#include <vector>
#include <list>
#include <iostream>
//VECTOR MEMBER FUNCTIONS
template <typename T>
miniStackVT<T>::miniStackVT() {
elementCount = 0;
content.resize(0);
}
template <typename T>
int miniStackVT<T>::size() const{
return content.size();
}
template <typename T>
bool miniStackVT<T>::IsEmpty() const{
return content.empty();
}
template <typename T>
void miniStackVT<T>::Push(const T& item) {
content.push_back(item);
elementCount++;
}
template <typename T>
void miniStackVT<T>::PrintStack() {
for(int i = elementCount - 1; i >= 0; i--) {
cout << content[i] << " | ";
}
}
template <typename T>
void miniStackVT<T>::Pop() {
content.pop_back();
elementCount--;
}
template <typename T>
T& miniStackVT<T>::TopStack() {
return content.back();
}
//LIST MEMBER FUNCTIONS
template <typename T>
miniStackLT<T>::miniStackLT() {
elementCount = 0;
content.resize(0);
}
template <typename T>
miniStackLT<T>::~miniStackLT() {
}
template <typename T>
int miniStackLT<T>::size() const{
return content.size();
}
template <typename T>
bool miniStackLT<T>::IsEmpty() const{
return content.empty();
}
template <typename T>
void miniStackLT<T>::Push(const T& item) {
content.push_back(item);
elementCount++;
}
template <typename T>
void miniStackLT<T>::PrintStack() {
list<T>::iterator rit;
for (auto rit = content.rbegin(); rit != content.rend(); ++rit) {
cout << *rit << " | ";
}
}
template <typename T>
void miniStackLT<T>::Pop() {
content.pop_back();
elementCount--;
}
//DARRAY DATA MEMBERS
template <typename T>
miniStackDA<T>::miniStackDA() {
arrSize = 50;
content = new T[arrSize];
elementCount = 0;
}
template <typename T>
miniStackDA<T>::~miniStackDA() {
delete[] content;
}
template <typename T>
int miniStackDA<T>::size() {
return elementCount;
}
template <typename T>
bool miniStackDA<T>::IsEmpty() {
if (elementCount == 0)
return true;
else return false;
}
template <typename T>
void miniStackDA<T>::Push(const T& item) {
if (elementCount < arrSize) {
content[elementCount] = item;
elementCount++;
}
else {
reserve(arrSize * 2, true);
content[elementCount] = item;
elementCount++;
}
}
template <typename T>
void miniStackDA<T>::reserve(int n, bool copy) {
T *newArr;
int i;
newArr = new T[n];
if (copy)
for (i = 0; i < elementCount; i++)
newArr[i] = content[i];
if (content != NULL)
delete[] content;
content = newArr;
elementCount = n;
}
template <typename T>
void miniStackDA<T>::PrintStack() {
for (int i = elementCount - 1; i >= 0; i--) {
cout << content[i] << " | ";
}
}
template <typename T>
void miniStackDA<T>::Pop() {
elementCount--;
}
template <typename T>
T& miniStackDA<T>::TopStack() {
return content[elementCount - 1];
}
miniQueue.cpp:
#include "miniQueue.h"
#include "iostream"
#include <vector>
#include <list>
using namespace std;
//START VECTOR MEMBER FUNCTIONS
template <typename T>
miniQueueVT<T>::miniQueueVT() {
elementCount = 0;
content.resize(0);
}
template <typename T>
miniQueueVT<T>::~miniQueueVT() {
}
template <typename T>
void miniQueueVT<T>::enqueue(const T& item) {
content.push_back(item);
elementCount++;
}
template <typename T>
void miniQueueVT<T>::dequeue() {
content.pop_back();
elementCount--;
}
template <typename T>
T& miniQueueVT<T>::front() {
return content.front();
}
template <typename T>
void miniQueueVT<T>::PrintQueue() const {
for (int i = elementCount - 1; i >= 0; i--) {
cout << content[i] << " | ";
}
}
template <typename T>
bool miniQueueVT<T>::IsEmpty() {
return content.empty();
}
template <typename T>
int miniQueueVT<T>::size() {
return elementCount;
}
//START LIST MEMBER FUNCTIONS
template <typename T>
miniQueueLT<T>::miniQueueLT() {
elementCount = 0;
content.resize(0);
}
template <typename T>
miniQueueLT<T>::~miniQueueLT() {
}
template <typename T>
void miniQueueLT<T>::enqueue(const T& item) {
content.push_back(item);
elementCount++;
}
template <typename T>
void miniQueueLT<T>::dequeue() {
content.pop_front();
elementCount--;
}
template <typename T>
T& miniQueueLT<T>::front() {
return content.front();
}
template <typename T>
void miniQueueLT<T>::PrintQueue() {
list<T>::iterator iter;
for (iter = content.begin(); iter != content.end(); iter++) {
cout << *iter << " | ";
}
}
template <typename T>
bool miniQueueLT<T>::IsEmpty() {
return content.empty();
}
template <typename T>
int miniQueueLT<T>::size() {
return content.size();
}
//START DYNAMIC ARRAY MEMBER FUNCTIONS
template <typename T>
miniQueueDA<T>::miniQueueDA() {
arrSize = 50;
content = new T[arrSize];
elementCount = 0;
}
template <typename T>
miniQueueDA<T>::~miniQueueDA() {
}
template <typename T>
void miniQueueDA<T>::enqueue(const T& item) {
if (elementCount < arrSize) {
content[elementCount] = item;
}
else {
reserve(arrSize * 2, true);
content[elementCount] = item;
elementCount++;
}
}
template <typename T>
void miniQueueDA<T>::dequeue() {
elementCount--;
}
template <typename T>
void miniQueueDA<T>::reserve(int n, bool copy) {
T *newArr;
int i;
newArr = new T[n];
if (copy) {
for (i = 0; i < elementCount; i++) {
newArr[i] = content[i];
}
}
if (content != NULL)
delete[] content;
content = newArr;
elementCount = n;
}
template <typename T>
T& miniQueueDA<T>::front() {
return content[0];
}
template <typename T>
bool miniQueueDA<T>::IsEmpty() {
if (elementCount == 0)
return true;
else return false;
}
template <typename T>
int miniQueueDA<T>::size() {
return elementCount;
}
template <typename T>
void miniQueueDA<T>::PrintQueue() {
for (int i = elementCount - 1; i >= 0; i--) {
cout << content[i] << " | ";
}
}
I'm getting the following errors when I go to compile the program:
Error LNK2019 unresolved external symbol "public: __thiscall miniStackVT<int>::~miniStackVT<int>(void)" (??1?$miniStackVT#H##QAE#XZ) referenced in function "void __cdecl StackVTMenu<int>(class miniStackVT<int>)" (??$StackVTMenu#H##YAXV?$miniStackVT#H###Z) Project 2 E:\Project 2\Project 2\Driver.obj 1
Error LNK2019 unresolved external symbol "public: int & __thiscall miniStackLT<int>::TopStack(void)" (?TopStack#?$miniStackLT#H##QAEAAHXZ) referenced in function "void __cdecl StackLTMenu<int>(class miniStackLT<int>)" (??$StackLTMenu#H##YAXV?$miniStackLT#H###Z) Project 2 E:\Project 2\Project 2\Driver.obj 1
Error LNK1120 2 unresolved externals Project 2 E:\Project 2\Debug\Project 2.exe 1
I have tried changing around which files are included in the main and the .h files. Right now i haveminiStack.cpp and miniQueue.cpp included in the main.
Any help would be greatly appreciated.
If you use templates in C++, your header file must contain implementations. If you only implement in your source files the compiler will compile each file and will link later.
But this cannot work in the case of templates since the compiler has to observe the generic type by checking its concrete usage.

Undefined reference C++ with template class [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Undefined reference error for template method
Splitting templated C++ classes into .hpp/.cpp files--is it possible?
I have this class:
matrix.h
#ifndef MATRIX_H
#define MATRIX_H
#include <vector>
#include <iostream>
using namespace std;
template <class T> class matrix;
template <typename T> ostream& operator<< (ostream& o, const matrix<T>& m);
template <class T>
class matrix
{
public:
matrix(const int&);
void push(const T&);
void setRows(const int&);
int size();
T& operator ()(const int&, const int&);
friend ostream& operator<< <>(ostream&, const matrix<T>&);
virtual ~matrix();
private:
vector<T> elements_;
int dimension_;
};
#endif // MATRIX_H
#include "matrix.h"
#include <vector>
matrix.cpp
template <class T>
matrix<T>::matrix(const int& n)
{
dimension_ = n;
}
template <class T>
void matrix<T>::push(const T& element)
{
elements_.resize( elements_.size() + 1, element);
}
template <class T>
int matrix<T>::size()
{
return elements_.size()/dimension_;
}
template <class T>
T& matrix<T>::operator ()(const int &n, const int &m)
{
if ((n < 0) || (n > dimension_))
{
cerr << "Row index out of range"
<< endl << endl;
}
if ((m < 0) || (m > dimension_))
{
cerr << "Column index out of range"
<< endl << endl;
}
return elements_[n*dimension_+m];
}
template <class T>
ostream& operator << (ostream& o, const matrix<T>& m)
{
for (int i = 0; i < m.size(); i++)
{
for (int j = 0; j < m.size(); i++)
{
o << m(i,j) << " ";
}
o << endl;
}
return o;
}
template <class T>
matrix<T>::~matrix()
{
//dtor
}
And this program:
#include "matrix.h"
#include <iostream>
using namespace std;
int main()
{
matrix<int> m(3);
m.push(10);
m.push(10);
m.push(11);
m.push(11);
m.push(12);
m.push(12);
m.push(13);
m.push(13);
m.push(10);
cout << m;
cout << "Hello world!" << endl;
return 0;
}
And for EACH. SINGLE. ONE. Of the methods I call, I get a compiler error like this one:
C:\Users...\main.cpp|8|undefined reference to
`matrix::matrix(int const&)'|
I have the matrix.cpp file built. I'm using Code::Blocks, so I have a matrix.o file in the obj folder. That's not the problem.
What is it?

Template Vector in C++

I've been having issues with using templates for a vector class. For some reason marime (size) is getting received as a pointer. I've managed to relieve the code of errors. Some help would be welcomed.
#include <iostream>
#include <stdio.h>
using namespace std;
template <class T>
class Vector {
private: int marime; T *vect;
public: Vector (int marime = 0){vect = new T[marime];}
~Vector (){
if ( vect != NULL ) delete [] vect;
}
int getMarime();
T getVect(int);
void setMarime(int);
void setVect(T,int);
Vector <T> operator+ (Vector);
Vector <T> operator= (Vector);
template <class U> friend istream & operator >>(istream, Vector);
template <class U> friend ostream & operator <<(ostream, Vector);
};
template <class T >
istream & operator>> (istream & in, Vector<T> & v)
{
T val;
int marime = v.getMarime();
for (int i=0;i<marime; i++) {
in>>val;
v.setVect(val,i);
}
return in;
}
template <class T>
ostream & operator<< (ostream& out, Vector<T> & v)
{
for (int i=0;i<v.getMarime(); i++)
out<<v.getVect(i)<< " " ;
return out;
}
template <class T>
int Vector<T>::getMarime(){
return marime;
}
template <class T>
T Vector<T>::getVect(int i){
return vect[i];
}
template <class T>
void Vector<T>::setMarime(int n){
this->marime = n;
}
template <class T>
void Vector<T>::setVect(T val, int i){
this->vect[i] = val;
}
template <class T>
Vector<T> Vector<T>::operator +(Vector<T> vector){
Vector<T> temp(marime + vector.marime);
for (int i=0; i < marime; i++)
temp.vect[i] = vect[i];
for (int i=marime+1; i<temp.marime; i++)
temp.vect[i] = vector.vect[i];
return *temp;
}
template <class T>
Vector<T> Vector<T>::operator= (Vector<T> vector){
Vector<T> temp(vector.marime);
for (int i=0; i < vector.marime; i++) temp.vect[i] = vector.vect[i];
return *temp;
}
int main() {
int n=3;
Vector <int> A(n);
cin>>A;
cout<<A;
return 0;
}
You are failing to initialize marime. You need to do this:
public: Vector (int marime = 0) : marime(marime) {vect = new T[marime];}
otherwise it just contains an essentially random value.
To avoid confusion it is probably better not to use the name of the member variable as a constructor parameter name. It is quite common to use naming conventions for member variables, such as starting with m_, or finishing with an underscore (marime_).
public: Vector (int marime = 0){vect = new T[marime];}
Shouldn't there be a this->marine = marime?

template string representation of vector of objects

I want to create a template function that generates a string representation of an array of things that have a name() method. The things might be kept by value, or by reference (raw or smart)
template< typename T>
struct GetStringRepresentation;
template< typename T>
struct GetStringRepresentation< std::vector< std::unique_ptr< T > > >
{
inline void ()( const std::vector< std::unique_ptr< T > >& seq, std::string& out )
{
size_t size = seq.size();
for (int i=0; i< size; i++)
{
if (i > 0)
out += ", ";
out += seq[i]->name();
}
}
};
template< typename T>
struct GetStringRepresentation< std::vector< std::shared_ptr< T > > >
{
inline void ()( const std::vector< std::shared_ptr< T > >& seq, std::string& out )
{
size_t size = seq.size();
for (int i=0; i< size; i++)
{
if (i > 0)
out += ", ";
out += seq[i]->name();
}
}
};
template< typename T>
struct GetStringRepresentation< std::vector< T* > >
{
inline void ()( const std::vector< T* >& seq, std::string& out )
{
size_t size = seq.size();
for (int i=0; i< size; i++)
{
if (i > 0)
out += ", ";
out += seq[i]->name();
}
}
};
template< typename T>
struct GetStringRepresentation< std::vector< T > >
{
inline void ()( const std::vector< T >& seq, std::string& out )
{
size_t size = seq.size();
for (int i=0; i< size; i++)
{
if (i > 0)
out += ", ";
out += seq[i].name();
}
}
};
As you can clearly see, there is a bunch of duplication, specially between the reference specializations. I'm not very up to speed with the best way to do this, i would like to see a better way that removes some, or all of the code duplication
Here's a tip to get you started: Specialize the print method only:
template <typename T> void print(T const & x)
{
std::cout << printer<T>::print(x) << std::endl;
}
template <typename T> struct printer
{
static std::string print(T const & x) { return x.name(); }
};
template <typename U> struct printer<U*>
{
static std::string print(U * p) { return p->name(); }
};
This way you only have to write the loop once, and the printer takes care of the details. You can even abstract this further and make a sort of is_pointer_like trait (everything that supports ->), which in turn you specialize for all the smart pointers:
printer<T, is_pointer_like<T>::value>::print(x); // etc.
template <typename T, bool> struct printer { /* as before */ }
template <typename T> struct printer<T, true>
{
static std::string print(T const & p) { return p->name(); }
};
// Traits:
template <typename T> struct is_pointer_like : std::false_type { };
template <typename U> struct is_pointer_like<U*> : std::true_type { };
template <typename U> struct is_pointer_like<std::shared_ptr<U>> : std::true_type { };
For a similar idea, see the pretty printer.
I would write this:
struct GetStringRepresentation
{
template<typename T>
std::string operator()(std::vector<T> const & seq)
{
std::string out;
size_t size = seq.size();
for (size_t i=0; i< size; i++)
{
if (i > 0)
out += ", ";
out += get(seq[i]); //call get() to get the string
}
return out;
}
private:
template<typename T>
std::string const & get(T const & t) { return t.name; }
template<typename T>
std::string const & get(T const * t) { return t->name; }
template<typename T>
std::string const & get(std::unique_ptr<T> const & t) { return t->name; }
template<typename T>
std::string const & get(std::shared_ptr<T> const & t) { return t->name; }
};