Reputation: 3523
I am looking at a code which uses new and delete to create pointers for classes and I am trying to update the code to use unique pointers. Here is my code.
#include <iostream>
#include <memory>
#include <vector>
class Algorithm
{
private:
public:
virtual void runn_algo() = 0;
virtual ~Algorithm() {};
};
class Algo1 : public Algorithm
{
void runn_algo()
{
std::cout << "running Algo1" << std::endl;
}
};
class Algo2 : public Algorithm
{
void runn_algo()
{
std::cout << "running Algo2" << std::endl;
}
};
class runner
{
public:
void runn_algo(std::unique_ptr<Algorithm> upa)
{
upa->runn_algo();
}
};
int main()
{
std::vector<std::unique_ptr<Algorithm>> algos;
algos.emplace_back(std::make_unique<Algo1>());
algos.emplace_back(std::make_unique<Algo1>());
algos.emplace_back(std::make_unique<Algo2>());
runner run;
for (auto i = 0u; i < algos.size(); ++i)
{
run.runn_algo(algos[i]);
}
}
I am getting the following error:
call to implicitly-deleted copy constructor of 'std::unique_ptr<Algorithm>'
run.runn_algo(algos[i]);
I am not sure why this is happening. the code with raw pointers is working fine
class runner
{
public:
void runn_algo(Algorithm* upa)
{
upa->runn_algo();
}
};
int main()
{
std::vector<Algorithm*> algos;
algos.push_back(new Algo1());
algos.push_back(new Algo1());
algos.push_back(new Algo2());
runner run;
for (auto i = 0u; i < algos.size(); ++i)
{
run.runn_algo(algos[i]);
}
}
Upvotes: 0
Views: 136
Reputation: 117856
First your emplace_back
should actually be a push_back
since you are using make_unique
algos.push_back(std::make_unique<Algo1>());
algos.push_back(std::make_unique<Algo1>());
algos.push_back(std::make_unique<Algo2>());
Second you should use virtual
and override
to make your methods polymorphic
virtual void runn_algo(); // base
void runn_algo() override; // derived
Third you should probably pass the argument as a raw (non-owning) pointer to your runner
, because if you try to pass unique_ptr
by value, it will try to copy, which is not allowed by a unique_ptr
void runn_algo(std::unique_ptr<Algorithm> alg); // nope, cannot copy
void runn_algo(Algorithm* alg); // ok, non-owning
for (auto i = 0u; i < algos.size(); ++i)
{
run.runn_algo(algos[i].get()); // access underlying pointer
}
Though in this case, I don't really see the point of the runner
as you can just use the polymorphism here
for (auto& alg : algos)
{
alg->run_algo(); // will be polymorphic
}
Upvotes: 2
Reputation: 5565
As the error message indicates, unique_ptr
doesn't have a copy constructor and so cannot be passed by value to a function. You can change the signature to accept a const std::unique_ptr<Algorithm>&
reference instead:
class runner
{
public:
void runn_algo(const std::unique_ptr<Algorithm>& upa)
{
upa->runn_algo();
}
};
Which produces the output
running Algo1
running Algo1
running Algo2
As expected.
Alternatively, write runner::runn_algo
in such a way that it doesn't care about how the Algorithm
is stored:
class runner
{
public:
void runn_algo(Algorithm& algo)
{
algo.runn_algo();
}
};
int main()
{
std::vector<std::unique_ptr<Algorithm>> algos;
algos.emplace_back(std::make_unique<Algo1>());
algos.emplace_back(std::make_unique<Algo1>());
algos.emplace_back(std::make_unique<Algo2>());
runner run;
for (auto i = 0u; i < algos.size(); ++i)
{
run.runn_algo(*algos[i]); // Dereference operator on algos[i]
}
}
Upvotes: 4