I have the template with this definition and call it as such.
#include <iostream>
template<class T>
class MyClass
{
public:
void Print(const T fooIn)
{
std::cout << fooIn->GetString() << std::endl;
}
};
class MyObject
{
private:
std::string str;
public:
MyObject(std::string str)
{
this->str = str;
}
std::string GetString()
{
return str;
}
};
template class MyClass<MyObject*>;
int main()
{
const MyObject* foo = new MyObject("test");
MyClass<MyObject*>* bar = new MyClass<MyObject*>();
bar->Print(foo);
return 0;
}
I get the error: "Cannot initialize a parameter of type Object *
with an lvalue of type const Object *
". I'm using Clangd
Since T=Object*
why would const T
not equal const Object *
?
I think that instead it has resolved to Object* const
And how would I make it so it has the desired functionality of being constant to the object it points to and I don't want to change the instantiation to const Object *
Like others (including myself in the comments) have mentioned, const T
resolves to a T* const
, or more concretely in your case Object* const
.
This doesn't jive well when you have a function that looks like this:
void Print(const T fooIn)
There are two approaches here, which I'm going to list in order of my recommendation:
template<class T>
class MyClass
{
public:
void Print(const T& fooIn) const
{
std::cout << fooIn.GetString() << std::endl;
}
};
Which you'd call like so:
class MyObject
{
private:
std::string str;
public:
MyObject(std::string str)
{
this->str = str;
}
std::string GetString() const
{
return str;
}
};
int main()
{
const MyObject* foo = new MyObject("test");
MyClass<MyObject> bar;
bar.Print(*foo);
delete foo;
}
If you must, add an overload to Print
that takes a pointer to const:
void Print(const T& fooIn) const
{
std::cout << fooIn.GetString() << std::endl;
}
void Print(const T* const fooIn) const
{
Print(*fooIn);
}
called like so:
int main()
{
const MyObject* foo = new MyObject("test");
MyClass<MyObject> bar;
bar.Print(*foo); // non-pointer
bar.Print(foo); // pointer
delete foo;
}
template<class T>
struct MyClass;
template<class T>
struct MyClass<T*> // specialized for T*
{
void Print(const T* const fooIn)
{
std::cout << fooIn->GetString() << std::endl;
}
};
class MyObject
{
private:
std::string str;
public:
MyObject(std::string str)
{
this->str = str;
}
std::string GetString() const
{
return str;
}
};
Called like so:
int main()
{
const MyObject* foo = new MyObject("test");
MyClass<MyObject*> bar;
bar.Print(foo);
delete foo;
}
N.B. There's probably a tagged dispatch implementation here, but I don't want to even try