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.
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.
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.