Reputation: 2268
I have a base class.
#include <string.h>
class Channel
{
private:
std::string stdstrName;
public:
Channel() : stdstrName("CHANNEL"){ }
Channel(std::string name) : stdstrName(name){ }
void PrintName() { std::cout << stdstrName << std::endl; }
};
which is inherited by Position class.
class PositionChannel : public Channel
{
public:
std::vector<int> keyframes;
PositionChannel() : Channel("POSITION") , keyframes( { 1 , 2, 3 }) { }
};
There is a director class which has the channel clas as its data members.
#include "Channel.h"
#include <memory>
class Director
{
private:
std::vector<std::shared_ptr<Channel>> channels;
public:
void AddChannel(std::shared_ptr<Channel> chn) { channels.push_back(chn); }
void GetChannel(Channel **chn) { *chn = channels[0].get(); }
};
now when in the main function.
// Free function
template<typename T>
void GetChannel(Director *dir)
{
T *chn;
dir->GetChannel(&chn);
}
Director dir;
PositionChannel channel;
std::shared_ptr<Channel> channelPointer = std::make_shared<Channel>(channel);
dir.AddChannel(channelPointer);
GetChannel< PositionChannel>(&dir); // here i get error
this is the error message error C2664: ' cannot convert argument 1 from 'T **' to 'Channel **
if i change the templated function to a non templted function than i do not get any error.
Upvotes: 0
Views: 84
Reputation: 1941
Yes, Daniel Langr already gave the correct answer. I added a check in the template if the class is derived.
#include <type_traits>
class Channel
{
public:
virtual ~Channel() = default;
};
class PositionChannel : public Channel
{
};
struct Director{
void GetChannel(Channel **c) {}
};
template <typename T,
typename = typename std::enable_if<std::is_base_of<Channel, T>::value, T>::type>
void GetChannel(Director *dir)
{
Channel *chn;
dir->GetChannel(&chn);
T* ptr = static_cast<T*>(chn);
}
int main(void) {
Director dir;
GetChannel<PositionChannel>(&dir);
return 0;
}
Upvotes: 0
Reputation: 23497
In you GetChannel
call, &chn
argument is of type PositionChannel**
, but the type of Director::GetChannel
parameter is Channel**
. These two types are not convertible; see, for example this question: Conversion of pointer-to-pointer between derived and base classes?.
I am not sure what are your intentions since the code does not make much sense as is, but you can redefine GetChannel
as follows:
template<typename T>
void GetChannel(Director *dir)
{
Channel* ptr;
dir->GetChannel(&ptr);
T *chn = ptr;
}
Upvotes: 4
Reputation: 2533
T
can be any type, you can't convert it to a Channel
for any type.
There are probably ways to make it work with templates, but I feel like your problem could be more easily solved by using polymorphism with something like this :
void GetChannel(Channel* chn, Director *dir)
{
dir->GetChannel(&chn);
}
And then chn
can be any type dervived from Channel
.
Upvotes: 1