hi guys :D!
im trying to make specialized template for cstring, but it seems i stuck on it..

i tried to search how to make specialized template for cstring , but there wasnt any good explanation and im trying to figure this out my self

here's my template header :

#ifndef CSTRINGVECTOR_H
#define CSTRINGVECTOR_H


#include <iostream>

template <char*>
class CstringVector
{
    private:
    char** aptr;
    int arraySize;
    void memError();
    void subError();

    public:
    CstringVector()
    {
        arraySize = 0;
        aptr = NULL;
    }
    CstringVector(int);
    CstringVector(const CstringVector&);
    ~CstringVector();
    int size() const
    {
        return arraySize;
    }
    char* getElementAt(const int);
    void setSize(const int);
    char* operator[](const int&);
    void push_back(const char*);
    void pop_back();

};


#endif

here's my source :

#include "CstringVector.h"
#include <iostream>
#include <cstdlib>
#include <new>

template <char*>
CstringVector<char*>::CstringVector(int s)
{
    arraySize = s;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }
    try
    {
        aptr = new char[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = 0;
    }
}

template <char*>
CstringVector<char*>::CstringVector(const CstringVector& x)
{
    arraySize = x.arraySize;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }
    aptr = new char[arraySize];
    if(aptr == 0)
    {
        memError();
    }
    for(int count = 0; count < arraySize;count++)
    {
        *(aptr+count) = *(x.aptr + count);
    }
}

template <char*>
CstringVector<char*>::~CstringVector()
{
    delete [] aptr;
}

template <char*>
void CstringVector<char*>::memError()
{
    std::cout<<"ERROR CANNOT ALLOCATE ! ENDING THE PROGRAM! ";
    exit(EXIT_FAILURE);
}

template <char*>
void CstringVector<char*>::subError()
{
    std::cout<<"INVALID SUBSCRIPT! ENDING PROGRAM";
    exit(EXIT_FAILURE);
}

template <char*>
char* CstringVector<char*>::getElementAt(const int s)
{
    if(s < 0 || s >= arraySize)
    {
        subError();
    }
    return aptr[s];
}

template <char*>
CstringVector<char*>::operator[](const int& s)
{
    if(s < 0||s >= arraySize)
    {
        subError();
    }
    return aptr[s];
}


template <char*>
void CstringVector<char*>::setSize(const int s)
{
    arraySize = s;
    try
    {
        aptr = new char[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = 0;
    }
}

template <char*>
void CstringVector<char*>::push_back(const char* x)
{

        char** temp = new char*[arraySize + 1];
        for(int index = 0; index < arraySize; index++)
        {
            temp[index] = aptr[index];
        }
        temp[arraySize++] = x;

        delete [] aptr;

        aptr = temp;

}

template <char*>
void CstringVector<char*>::pop_back()
{
    if(arraySize == 0 || aptr == NULL)
    {
        std::cout<<"cannot pop back! \n";
        return;
    }
    char** temp = new char*[arraySize];

    for(int index = 0; index < arraySize; index++)
    {
        temp[index] = aptr[index];
    }
    temp[arraySize--];

    delete [] aptr;

    aptr = temp;

}

Recommended Answers

All 8 Replies

my questions are :

how to make specialized template for cstring? anyone have link or can explain please?
because from the link i searched, i didnt get any good explanation and still dont understand how to make specialized template

edit :
based for what i got from searchengine, i change my code to :
header :

#ifndef CSTRINGVECTOR_H
#define CSTRINGVECTOR_H


#include <iostream>

template <typename Type>
class CstringVector
{
    private:
    Type* aptr;
    int arraySize;
    void memError();
    void subError();

    public:
    CstringVector()
    {
        arraySize = 0;
        aptr = NULL;
    }
    CstringVector(int);
    CstringVector(const CstringVector&);
    ~CstringVector();
    int size() const
    {
        return arraySize;
    }
    Type getElementAt(const int);
    void setSize(const int);
    Type operator[](const int&);
    void push_back(Type);
    void pop_back();

};


#endif

and this is my source :

#include "CstringVector.h"
#include <iostream>
#include <cstdlib>
#include <new>

template <>
CstringVector<char*>::CstringVector(int s)
{
    arraySize = s;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }
    aptr = new char*[arraySize];

    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = 0;
    }
}

template <>
CstringVector<char*>::CstringVector(const CstringVector<char*> &x)
{
    arraySize = x.arraySize;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }
    aptr = new char*[arraySize];
    if(aptr == 0)
    {
        memError();
    }
    for(int count = 0; count < arraySize;count++)
    {
        *(aptr+count) = *(x.aptr + count);
    }
}

template <>
CstringVector<char*>::~CstringVector()
{
    delete [] aptr;
}

template <typename Type>
void CstringVector<Type>::memError()
{
    std::cout<<"ERROR CANNOT ALLOCATE ! ENDING THE PROGRAM! ";
    exit(EXIT_FAILURE);
}

template <typename Type>
void CstringVector<Type>::subError()
{
    std::cout<<"INVALID SUBSCRIPT! ENDING PROGRAM";
    exit(EXIT_FAILURE);
}

template <>
char* CstringVector<char*>::getElementAt(const int s)
{
    if(s < 0 || s >= arraySize)
    {
        subError();
    }
    return aptr[s];
}

template <>
char* CstringVector<char*>::operator[](const int& s)
{
    if(s < 0||s >= arraySize)
    {
        subError();
    }
    return aptr[s];
}


template <>
void CstringVector<char*>::setSize(const int s)
{
    arraySize = s;
    try
    {
        aptr = new char*[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = 0;
    }
}

template <>
void CstringVector<char*>::push_back(char* x)
{

        char** temp = new char*[arraySize + 1];
        for(int index = 0; index < arraySize; index++)
        {
            temp[index] = aptr[index];
        }
        temp[arraySize++] = x;

        delete [] aptr;

        aptr = temp;

}

template <>
void CstringVector<char*>::pop_back()
{
    if(arraySize == 0 || aptr == NULL)
    {
        std::cout<<"cannot pop back! \n";
        return;
    }
    char** temp = new char*[arraySize];

    for(int index = 0; index < arraySize; index++)
    {
        temp[index] = aptr[index];
    }
    temp[arraySize--];

    delete [] aptr;

    aptr = temp;

}

and i got many compiler errors that said about multiple definitions ..

To do the specialization, you must repeat the full declaration of the class for the special case, as so:

// general template:
template <typename T>
class my_vector {
  private:
    T* data;
    std::size_t data_size;
  public:
    //...
    void set_element(std::size_t i, const T& value);
};

// specialized template
template <>
class my_vector< char* > {
  private:
    char** data;
    std::size_t data_size;
  public:
    //...
    void set_element(std::size_t i, const char* value);
};

// implementations:

// ...

template <typename T>
void my_vector<T>::set_element(std::size_t i, const T& value) {
  data[i] = value;
};

// ... 

template <>
void my_vector<char*>::set_element(std::size_t i, const char* value) {
  std::size_t val_len = std::strlen(value);
  delete data[i];
  data[i] = new char[ val_len + 1 ];
  std::memcpy(data[i], value, val_len + 1);
};

If you want to only specialize a few functions and reuse the general functions for most other things, then you need to create a second class that implements only those "to-be-specialized" functions and then do a template specialization on that class instead. Or, you can do it as free functions, which you overload for the special cases, as so:

// general template only:
template <typename T>
class my_vector {
  private:
    T* data;
    std::size_t data_size;
  public:
    //...
    void set_element(std::size_t i, const T& value);
};

// set-element implementation function:
template <typename T>
void set_element_impl(T* data, std::size_t i, const T& value) {
  data[i] = value;
};

// set-element implementation for special case:
void set_element_impl(char** data, std::size_t i, const char* value) {
  std::size_t val_len = std::strlen(value);
  delete data[i];
  data[i] = new char[ val_len + 1 ];
  std::memcpy(data[i], value, val_len + 1);
};

// then, call the implementation function within the member function:
template <typename T>
void my_vector<T>::set_element(std::size_t i, const T& value) {
  set_element_impl(data, i, value);
};

okay i got it, i changed my code and add repeat full declaration in the SimpleVector class
but i got some errorsagain, it says :
"template-id 'SimpleVector<>' for 'SimpleVector<char>::SimpleVector(const SimpleVector<char>&)' does not match any template declaration"

then i tried to copy the function inside the header file(make it inline) and there's no errors in that function i copied, but the other functions inside the implementation file have errors, how do i fix this? :s

erm 1 more question , when declaring template :
template <class Type>
is that (above) is the same as : template <typename Type> ?

thx :D

First of all, templates cannot be split into a header and cpp file like normal classes or functions. Read this FAQ for an explanation. So, that might be the root of some of the errors.

As for the actual error you pointed out, I cannot tell you what's wrong if I don't have the code in question.

As for class versus typename in the template argument declaration, there is no difference whatsoever between the two. It is only a matter of preferrence. In my experience, it seems typename is more conventionally used than class. I personally prefer it too, just because the class keyword can be a bit misleading, as to think that the type in question has to be a user-defined class (e.g., class Foo { }; or something), when in reality it can stand for any type, and thus, the keyword typename sounds more clear to me.

this is my code, now i put them together in the header file but i get errors that say "error : template-id for (all the functions) does not match any template declaration"
(sorry for the long post D: )

#ifndef SIMPLEVECTOR_H
#define SIMPLEVECTOR_H
#include <cstdlib>
#include <iostream>
#include <new>
#include <iostream>

template <typename Type>
class SimpleVector
{
    private:
    char* aptr;
    int arraySize;
    void memError();
    void subError();

    public:
    SimpleVector()
    {
        arraySize = 0;
        aptr = NULL;
    }
    SimpleVector(int s);
    SimpleVector(const SimpleVector&);
    ~SimpleVector();
    int size() const
    {
        return arraySize;
    }
    Type getElementAt(const int);
    void setSize(const int);
    Type& operator[](const int&);
    void push_back(const Type&);
    void pop_back();

};


template <>
class SimpleVector<char*>
{
    private:
    char** aptr;
    int arraySize;
    void memError()
    {
        std::cout<<"ERROR CANNOT ALLOCATE ! ENDING THE PROGRAM! ";
        exit(EXIT_FAILURE);
    }
    void subError()
    {

        std::cout<<"INVALID SUBSCRIPT! ENDING PROGRAM";
        exit(EXIT_FAILURE);
    }

    public:
    SimpleVector();
    SimpleVector(int s);
    SimpleVector(const SimpleVector&);
    ~SimpleVector();
    int size() const
    {
        return arraySize;
    }
    char* getElementAt(const int);
    void setSize(const int);
    char* operator[](const int&);
    void push_back(const char*);
    void pop_back();


};


template <typename Type>
SimpleVector<Type>::SimpleVector(int s)
{
    arraySize = s;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }
    try
    {
        aptr = new Type[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }


    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = 0;
    }
}


template <typename Type>
SimpleVector<Type>::SimpleVector(const SimpleVector& x)
{
    arraySize = x.arraySize;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }

    try
    {
        aptr = new Type[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int count = 0; count < arraySize;count++)
    {
        *(aptr+count) = *(x.aptr + count);
    }
}

template <typename Type>
SimpleVector<Type>::~SimpleVector()
{
    delete [] aptr;
}

template <typename Type>
void SimpleVector<Type>::memError()
{
    std::cout<<"ERROR CANNOT ALLOCATE ! ENDING THE PROGRAM! ";
    exit(EXIT_FAILURE);
}

template <typename Type>
void SimpleVector<Type>::subError()
{
    std::cout<<"INVALID SUBSCRIPT! ENDING PROGRAM";
    exit(EXIT_FAILURE);
}

template <typename Type>
Type SimpleVector<Type>::getElementAt(const int s)
{
    if(s < 0 || s >= arraySize)
    {
        subError();
    }
    return aptr[s];
}

template <typename Type>
Type& SimpleVector<Type>::operator[](const int& s)
{
    if(s < 0||s >= arraySize)
    {
        subError();
    }
    return aptr[s];
}


template <typename Type>
void SimpleVector<Type>::setSize(const int s)
{
    arraySize = s;

    try
    {
        aptr = new Type[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = 0;
    }
}

template <typename Type>
void SimpleVector<Type>::push_back(const Type& x)
{

        Type temp;
        try
        {
            temp = new Type[arraySize + 1];
        }
        catch(std::bad_alloc)
        {
            memError();
        }

        for(int index = 0; index < arraySize; index++)
        {
            temp[index] = aptr[index];
        }
        temp[arraySize++] = x;

        delete [] aptr;

        aptr = temp;

}

template <typename Type>
void SimpleVector<Type>::pop_back()
{
    if(arraySize == 0 || aptr == NULL)
    {
        std::cout<<"cannot pop back! \n";
        return;
    }
    Type temp;
    try
    {
        temp = new Type[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }
    for(int index = 0; index < arraySize; index++)
    {
        temp[index] = aptr[index];
    }
    temp[arraySize--];

    delete [] aptr;

    aptr = temp;

}

template <>
SimpleVector<char*>::SimpleVector(int s)
{
    arraySize = s;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }

    try
    {
        aptr = new char*[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = NULL;
    }
}

template <>
SimpleVector<char*>::SimpleVector(const SimpleVector &x)
{
    arraySize = x.arraySize;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }

    try
    {
        aptr = new char*[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    if(aptr == 0)
    {
        memError();
    }

    for(int count = 0; count < arraySize;count++)

    {
        *(aptr+count) = *(x.aptr[count]);
    }
}

template <>
SimpleVector<char*>::~SimpleVector()
{
    delete [] aptr;
}

template <>
int SimpleVector<char*>::size() const
{
    return arraySize;
}
template<>
char* SimpleVector<char*>::getElementAt(const int s)
{
    if(s < 0 || s >= arraySize)
    {
        subError();
    }

    return aptr[s];
}

template <>
void SimpleVector<char*>::setSize(const int s)
{
    arraySize = s;

    try
    {
        aptr = new char*[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = 0;
    }
}

template <>
char* SimpleVector<char*>::operator[](const int& s)
{
    if(s < 0||s >= arraySize)
    {
        subError();
    }
    return aptr[s];
}

template <>
void SimpleVector<char*>::push_back(char* x)
{
    char** temp;
    try
    {
       temp = new char*[arraySize + 1];
    }
    catch(std::bad_alloc)
    {
        memError();
    }
    for(int index = 0; index < arraySize; index++)
    {
        temp[index] = aptr[index];
    }
    temp[arraySize++] = x;

    delete [] aptr;

    aptr = temp;
}

template <>
void SimpleVector<char*>::pop_back()
{
    if(arraySize == 0 || aptr == NULL)
    {
        std::cout<<"cannot pop back! \n";
        return;
    }

    try
    {
       temp = new char*[arraySize + 1];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int index = 0; index < arraySize; index++)
    {
        temp[index] = aptr[index];
    }
    temp[arraySize--];

    delete [] aptr;

    aptr = temp;
}

#endif

Ok, so the solution to all your little mismatch errors is that the template <> is not needed before the function definitions. Sorry about that, it slipped my mind.

You also had a lot of errors in addition to that. I went ahead and solved a few of them, at least, to get it to compile. However, your implementation of the char* specialization is very wrong and is leaking memory all over the place, you will probably need to revise it entirely, but my guess is that you just didn't get to that point yet, now you are, with this corrected code:

#ifndef SIMPLEVECTOR_H
#define SIMPLEVECTOR_H
#include <cstdlib>
#include <iostream>
#include <new>
#include <iostream>
#include <cstring>

template <typename Type>
class SimpleVector
{
    private:
    Type* aptr;
    int arraySize;
    void memError();
    void subError();

    public:
    SimpleVector(int s = 0);
    SimpleVector(const SimpleVector&);
    ~SimpleVector();
    int size() const
    {
        return arraySize;
    }
    Type getElementAt(int);
    void setSize(int);
    Type& operator[](int);
    void push_back(const Type&);
    void pop_back();

};


template <>
class SimpleVector<char*>
{
    private:
    char** aptr;
    int arraySize;
    void memError()
    {
        std::cout<<"ERROR CANNOT ALLOCATE ! ENDING THE PROGRAM! ";
        exit(EXIT_FAILURE);
    }
    void subError()
    {

        std::cout<<"INVALID SUBSCRIPT! ENDING PROGRAM";
        exit(EXIT_FAILURE);
    }

    public:
    SimpleVector(int s = 0);
    SimpleVector(const SimpleVector<char*>&);
    ~SimpleVector();
    int size() const
    {
        return arraySize;
    }
    char* getElementAt(int);
    void setSize(int);
    char* operator[](int);
    void push_back(const char*);
    void pop_back();


};


template <typename Type>
SimpleVector<Type>::SimpleVector(int s)
{
    arraySize = s;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }
    try
    {
        aptr = new Type[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }


    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = 0;
    }
}


template <typename Type>
SimpleVector<Type>::SimpleVector(const SimpleVector& x)
{
    arraySize = x.arraySize;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }

    try
    {
        aptr = new Type[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int count = 0; count < arraySize;count++)
    {
        *(aptr+count) = *(x.aptr + count);
    }
}

template <typename Type>
SimpleVector<Type>::~SimpleVector()
{
    delete [] aptr;
}

template <typename Type>
void SimpleVector<Type>::memError()
{
    std::cout<<"ERROR CANNOT ALLOCATE ! ENDING THE PROGRAM! ";
    exit(EXIT_FAILURE);
}

template <typename Type>
void SimpleVector<Type>::subError()
{
    std::cout<<"INVALID SUBSCRIPT! ENDING PROGRAM";
    exit(EXIT_FAILURE);
}

template <typename Type>
Type SimpleVector<Type>::getElementAt(int s)
{
    if(s < 0 || s >= arraySize)
    {
        subError();
    }
    return aptr[s];
}

template <typename Type>
Type& SimpleVector<Type>::operator[](int s)
{
    if(s < 0||s >= arraySize)
    {
        subError();
    }
    return aptr[s];
}


template <typename Type>
void SimpleVector<Type>::setSize(int s)
{
    arraySize = s;

    try
    {
        aptr = new Type[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = 0;
    }
}

template <typename Type>
void SimpleVector<Type>::push_back(const Type& x)
{

        Type temp;
        try
        {
            temp = new Type[arraySize + 1];
        }
        catch(std::bad_alloc)
        {
            memError();
        }

        for(int index = 0; index < arraySize; index++)
        {
            temp[index] = aptr[index];
        }
        temp[arraySize++] = x;

        delete [] aptr;

        aptr = temp;

}

template <typename Type>
void SimpleVector<Type>::pop_back()
{
    if(arraySize == 0 || aptr == NULL)
    {
        std::cout<<"cannot pop back! \n";
        return;
    }
    Type temp;
    try
    {
        temp = new Type[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }
    for(int index = 0; index < arraySize; index++)
    {
        temp[index] = aptr[index];
    }
    temp[arraySize--];

    delete [] aptr;

    aptr = temp;

}

//template <>
SimpleVector<char*>::SimpleVector(int s)
{
    arraySize = s;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }

    try
    {
        aptr = new char*[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = NULL;
    }
}

//template <>
SimpleVector<char*>::SimpleVector(const SimpleVector<char*> &x)
{
    arraySize = x.arraySize;
    if(arraySize == 0)
    {
        aptr = NULL;
        return;
    }

    try
    {
        aptr = new char*[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    if(aptr == 0)
    {
        memError();
    }

    for(int count = 0; count < arraySize;count++)

    {
        aptr[count] = x.aptr[count];
    }
}

SimpleVector<char*>::~SimpleVector()
{
    delete [] aptr;
}

char* SimpleVector<char*>::getElementAt(int s)
{
    if(s < 0 || s >= arraySize)
    {
        subError();
    }

    return aptr[s];
}

void SimpleVector<char*>::setSize(int s)
{
    arraySize = s;

    try
    {
        aptr = new char*[arraySize];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int count = 0; count < arraySize; count++)
    {
        *(aptr + count) = 0;
    }
}

char* SimpleVector<char*>::operator[](int s)
{
    if(s < 0||s >= arraySize)
    {
        subError();
    }
    return aptr[s];
}

void SimpleVector<char*>::push_back(const char* x)
{
    char** temp;
    try
    {
       temp = new char*[arraySize + 1];
    }
    catch(std::bad_alloc)
    {
        memError();
    }
    for(int index = 0; index < arraySize; index++)
    {
        temp[index] = aptr[index];
    }
    std::size_t len = std::strlen(x);
    temp[arraySize++] = new char[len + 1];
    std::memcpy(temp[arraySize-1], x, len + 1);

    delete [] aptr;

    aptr = temp;
}

void SimpleVector<char*>::pop_back()
{
    if(arraySize == 0 || aptr == NULL)
    {
        std::cout<<"cannot pop back! \n";
        return;
    }

    char** temp;
    try
    {
       temp = new char*[arraySize + 1];
    }
    catch(std::bad_alloc)
    {
        memError();
    }

    for(int index = 0; index < arraySize; index++)
    {
        temp[index] = aptr[index];
    }
    temp[arraySize--];

    delete [] aptr;

    aptr = temp;
}

#endif

wow thx! that helps alot :D

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.