Hey when I don't template my classes, I can pass member functions to eachother normally. But when I template it, I get errors. The two functions are defined as so:

CustomType& Delete(int Position);

CustomType& Delete(T ValueToDelete, bool All = false);

CustomType& Delete(CustomType ValuesToDelete);

And Implemented like this:

template<typename T>
CustomType<T>& CustomType<T>::Delete(T ValueToDelete, bool All)
{
    for (size_t I = 0; I < TypeData.size(); I++)
        if (TypeData[I] == ValueToDelete)
        {
            TypeData.erase(TypeData.begin() + I);
            if (!All)
                break;
            I = 0;
        }
    return *this;
}

template<typename T>
CustomType<T>& CustomType<T>::Delete(CustomType ValuesToDelete)
{
    for (size_t I = 0; I < ValuesToDelete.size(); I++)
    {
        this->Delete(ValuesToDelete[I], true);  //The error below points to this line.
    }
    return *this;
}

Used like:

int main()
{
    CustomType<int> CT(1, 5, 4, 7, 9, 14, 23, 89);
    CT.Delete(CT);  //FAILS!
}

//error: no matching function for call to 'CustomType<int>::Delete(CustomType<int>&, bool)'

When my classes aren't templated, these functions work perfectly fine. I do not understand why it doesn't work now :S Any help is appreciated.

Recommended Answers

All 6 Replies

I can't reproduce the error because too many things are missing. Can you boil it down into a small and complete program that's compilable as-is? Also, what compiler are you using?

Typo?

template<typename T>
CustomType<T>& CustomType<T>::Delete(CustomType<T> ValuesToDelete) // notice the <T> here.

Hmm without the <T> it's the same thing no? It still gave the same error.
It's quite long which is why I didn't post the whole thing. I ended up fixing the error late last night. I had to change CustomType& to T& for my overload of the operator []. My only problem now is the Contains function which I tried to specialize but when I do:

#include <windows.h>
#include <iostream>
#include "Templates.hpp"

using namespace std;

int main(int argc, char* argv[])
{
    //StreamFlags(cout);

    const char Meh[] = "MM";
    CustomType<const char*> SA("MM");

    cout<<SA.Contains(Meh, true);

    cin.get();
    return 0;
}

It will give me an error saying I cannot overload Contains with Contains for char*'s. The entire compilable header (Only compiles with Mingw 4.7+ or Codeblocks using Mingw4.7+ due to the variadic template constructors) Lines 51, 53, and 55 which is defined at lines 208, is my problem now:

#ifndef TEMPLATES_HPP_INCLUDED
#define TEMPLATES_HPP_INCLUDED

#include <vector>
#include <assert.h>
#include <sstream>

template <typename T>
class CustomType
{
    private:
        std::vector<T> TypeData;
        void Insert();
        template<typename A, typename... Args>
        CustomType& Insert(A FirstArg, const Args... RemainingArgs);

    public:
        CustomType();
        template<typename A, typename... Args>
        CustomType(A FirstArg, const Args... RemainingArgs);
        ~CustomType();

        size_t size() const;

        T& operator [](int I);

        const T& operator [](int I) const;

        operator const std::vector<T>& () const;

        bool operator == (const CustomType &CT) const;

        bool operator != (const CustomType &CT) const;

        CustomType& operator = (const CustomType &CT);

        CustomType& operator += (const T& t);

        CustomType& operator += (const CustomType& CT);

        CustomType operator + (const T& t);

        CustomType operator + (const CustomType& CT);

        CustomType& Delete(int Position);

        CustomType& Delete(T ValueToDelete, bool All = false);

        CustomType& Delete(CustomType ValuesToDelete);

        bool Contains(T LiteralType, bool CaseSensitive = true);

        bool Contains(const std::string& LiteralType, bool CaseSensitive = true);

        bool Contains(const char* LiteralType, bool CaseSensitive = true);

        CustomType& operator << (const T& t);

        void SetLength(size_t NewLength);

        template<typename A, typename... Args>
        CustomType& operator ()(A FirstArg, const Args... RemainingArgs);

        friend std::ostream& operator << (std::ostream& Str, const CustomType &CT)        //For use with Writeln & cout.
        {
            if (!CT.TypeData.empty())
            {
                Str<<"[";
                for (size_t I = 0; I < CT.TypeData.size() - 1; I++)
                {
                    Str<<CT.TypeData[I];
                    Str<<", ";
                }
                Str<<CT.TypeData[CT.TypeData.size() - 1];
                Str<<"]";
            }
            else
            {
                Str<<"[]";
            }
            return Str;
        }
};



/**      Non-Inline Implementation  **/

template<typename T>
void CustomType<T>::Insert(){}

template<typename T>
CustomType<T>::CustomType(){}

template<typename T>
CustomType<T>::~CustomType(){}

template<typename T>
size_t CustomType<T>::size() const
{
    return TypeData.size();
}

template<typename T>
T& CustomType<T>::operator [](int I)
{
    assert(I >= 0 && !TypeData.empty());
    return TypeData[I];
}

template<typename T>
const T& CustomType<T>::operator [](int I) const
{
    assert(I >= 0 && !TypeData.empty());
    return TypeData[I];
}

template<typename T>
CustomType<T>::operator const std::vector<T>& () const
{
    return TypeData;
}

template<typename T>
bool CustomType<T>::operator == (const CustomType &CT) const
{
    return (TypeData == CT.TypeData);
}

template<typename T>
bool CustomType<T>::operator != (const CustomType &CT) const
{
    return !(TypeData == CT.TypeData);
}

template<typename T>
CustomType<T>& CustomType<T>::operator = (const CustomType &CT)
{
    if (this != &CT)
    {
        if (TypeData.size() > 0)
            TypeData.clear();

        for (size_t I = 0; I < CT.TypeData.size(); I++)
            TypeData.push_back(CT.TypeData[I]);
    }
    return *this;
}

template<typename T>
CustomType<T>& CustomType<T>::operator += (const T& t)
{
    TypeData.push_back(t);
    return *this;
}

template<typename T>
CustomType<T>& CustomType<T>::operator += (const CustomType& CT)
{
    TypeData.insert(TypeData.end(), CT.TypeData.begin(), CT.TypeData.end());
    return *this;
}

template<typename T>
CustomType<T> CustomType<T>::operator + (const T& t)
{
    return (CustomType<T>(*this) += t);
}

template<typename T>
CustomType<T> CustomType<T>::operator + (const CustomType& CT)
{
    return (CustomType<T>(*this) += CT);
}

template<typename T>
CustomType<T>& CustomType<T>::Delete(int Position)
{
    TypeData.erase(TypeData.begin() + Position);
    return *this;
}

template<typename T>
CustomType<T>& CustomType<T>::Delete(T ValueToDelete, bool All)
{
    for (size_t I = 0; I < TypeData.size(); I++)
        if (TypeData[I] == ValueToDelete)
        {
            TypeData.erase(TypeData.begin() + I);
            if (!All)
                break;
            I = 0;
        }
    return *this;
}

template<typename T>
CustomType<T>& CustomType<T>::Delete(CustomType ValuesToDelete)
{
    for (size_t I = 0; I < ValuesToDelete.size(); I++)
    {
        this->Delete(ValuesToDelete[I], true);
    }
    return *this;
}

template<typename T>
bool CustomType<T>::Contains(T LiteralType, bool CaseSensitive)
{
    for (size_t I = 0; I < TypeData.size(); I++)
    {
        if (TypeData[I] == LiteralType)
            return true;
    }
    return false;
}

template<>
bool CustomType<char>::Contains(char LiteralType, bool CaseSensitive)
{
    char Temp = LiteralType;
    std::vector<char> TempData = TypeData;
    if (!CaseSensitive)
    {
        Temp = tolower(Temp);

        for (size_t I = 0; I < TempData.size(); I++)
            TempData[I] = tolower(TempData[I]);
    }
    for (size_t I = 0; I < TempData.size(); I++)
    {
        if (TempData[I] == Temp)
            return true;
    }
    return false;
}

template<>
bool CustomType<std::string>::Contains(const std::string& LiteralType, bool CaseSensitive)
{
    std::string Temp(LiteralType);
    std::vector<std::string> TempData = TypeData;
    if (!CaseSensitive)
    {
        for (size_t I = 0; I < Temp.size(); I++)
            Temp[I] = tolower(Temp[I]);

        for (size_t I = 0; I < TempData.size(); I++)
            for (size_t J = 0; J < TempData[I].size(); J++)
                TempData[I][J] = tolower(TempData[I][J]);
    }
    for (size_t I = 0; I < TempData.size(); I++)
    {
        if (TempData[I] == Temp)
            return true;
    }
    return false;
}

template<>
bool CustomType<char*>::Contains(const char* LiteralType, bool CaseSensitive)
{
    std::string Temp(LiteralType);
    std::vector<std::string> TempData;

    for (size_t I = 0; I < TypeData.size(); I++)
        TempData[I] = TypeData[I];

    if (!CaseSensitive)
    {
        for (size_t I = 0; I < Temp.size(); I++)
            Temp[I] = tolower(Temp[I]);

        for (size_t I = 0; I < TempData.size(); I++)
            for (size_t J = 0; J < TempData[I].size(); J++)
                TempData[I][J] = tolower(TempData[I][J]);
    }
    for (size_t I = 0; I < TempData.size(); I++)
    {
        if (TempData[I] == Temp)
            return true;
    }
    return false;
}

template<typename T>
CustomType<T>& CustomType<T>::operator << (const T& t)
{
    TypeData.push_back(t);
    return *this;
}

template<typename T>
void CustomType<T>::SetLength(size_t NewLength)
{
    this->TypeData.resize(NewLength);
}

template<typename T>
template<typename A, typename... Args>
CustomType<T>& CustomType<T>::Insert(A FirstArg, const Args... RemainingArgs)
{
    this->TypeData.push_back(FirstArg);
    Insert(RemainingArgs...);
    return *this;
}

template<typename T>
template<typename A, typename... Args>
CustomType<T>::CustomType(A FirstArg, const Args... RemainingArgs)
{
    this->TypeData.push_back(FirstArg);
    Insert(RemainingArgs...);
}

template<typename T>
template<typename A, typename... Args>
CustomType<T>& CustomType<T>::operator ()(A FirstArg, const Args... RemainingArgs)
{
    this->TypeData.push_back(FirstArg);
    Insert(RemainingArgs...);
    return *this;
}

#endif // TEMPLATES_H_INCLUDED
bool Contains(const char* LiteralType, bool CaseSensitive = true);

This declaration doesn't need to exist at all. const char* is already handled in your specialization of the overload for T. So remove that entirely and the compile time error will go away. However, you'll still have a runtime error from this:

std::vector<std::string> TempData;
for (size_t I = 0; I < TypeData.size(); I++)
    TempData[I] = TypeData[I];

Notice how the vector is never properly resized, yet you still try to access an index. Replace that with a call to push_back() and you'll be golden.

commented: Thank you! Much Appreciated. +5

Ahh I fixed the run-time error but the compile time still happens. If I remove the declaration, instead it will say:

error: template-id 'Contains<>' for 'bool CustomType<char*>::Contains(const char*, bool)' does not match any template declaration

note: saw 1 'template<>', need 2 for specializing a member function template

And thank you for taking the time to look through it =] Much Appreciated.

EDIT:

I changed the template to (And remove the declarations for both):

template<>
bool CustomType<std::string>::Contains(std::string LiteralType, bool CaseSensitive)
{
    //.........
}

template<>
bool CustomType<const char*>::Contains(const char* LiteralType, bool CaseSensitive)
{
    //........
}


//Had to make one for char* without the const so that it works for that too.
template<>
bool CustomType<char*>::Contains(char* LiteralType, bool CaseSensitive)
{
    //.......
}

Thank you! =]

Ahh I fixed the run-time error but the compile time still happens

Whoops. I forgot to mention that I also changed the specialization from char* to const char* to fix the compile time error. My bad.

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.