Reputation: 1559
I am trying to create a Recursive Function in a factory pattern that iterates through a std::tuple with a variable number of elements. I have created my ConsoleShapeFactory like this:
template<size_t N, typename...Shapes>
class ConsoleShapeFactory : public ShapeFactory {
private:
//Functions for shape creation
void MakePoint(std::shared_ptr<CAD::Point>);
//Recursive Router for shapes
void MakeShapeRouter(std::tuple<Shapes...>&);
public:
//Create Object Function
std::tuple<Shapes...> CreateShapeTuple();
};
The CreateShapeTuple method is defined like this:
template<size_t N, typename...Shapes>
std::tuple<Shapes...> ConsoleShapeFactory<N, Shapes...>::CreateShapeTuple() {
//Define return tuple and get size
std::tuple<Shapes...> returnTuple;
MakeShapeRouter(returnTuple);
return returnTuple;
}
And the recursive MakeShapeRouter function looks like this (this does not work):
template<size_t N, typename...Shapes>
void ConsoleShapeFactory<N, Shapes...>::MakeShapeRouter(std::tuple<Shapes...>& tupShapes) {
MakePoint(std::tuple::get<N-1>(tupShapes));
ConsoleShapeFactory<N-1, Shapes...>::MakeShapeRouter(tupShapes); //This doesn't work
}
And my attempt at a base case looks like this:
template<size_t N, typename...Shapes>
void ConsoleShapeFactory<1, Shapes...>::MakeShapeRouter(std::tuple<Shapes...>& tupShapes) {
MakePoint(std::tuple::get<0>(tupShapes));
}
I am not sure how to set up my MakeShapeRouter function so that it can be called recursively and exit with a base case. Is what I am trying to do even possible?
*edit
Here is how I want to call the function in my main method if that helps:
int main()
{
auto factory = ConsoleShapeFactory<2, std::shared_ptr<CAD::Point>, std::shared_ptr<CAD::Point>>();
std::tuple<std::shared_ptr<CAD::Point>, std::shared_ptr<CAD::Point>> shapeTuple = factory.CreateShapeTuple();
return 0;
}
*Edit 2
MakePoint implementation:
template<typename...Shapes>
void ConsoleShapeFactory<Shapes...>::MakePoint(std::shared_ptr<CAD::Point>& sp_point) {
double x, y;
x = 3;
y = 4;
sp_point = std::make_shared<CAD::Point>(x,y);
};
Upvotes: 1
Views: 586
Reputation: 217283
Your method are not static
, so you need an instance to call them.
ConsoleShapeFactory<N-1, Shapes...>::MakeShapeRouter(tupShapes); //This doesn't work
should be
ConsoleShapeFactory<N-1, Shapes...>{}.MakeShapeRouter(tupShapes);
But thing can be done without recursion thanks to std::index_sequence
, something like:
template<typename... Shapes>
class ConsoleShapeFactory : public ShapeFactory {
private:
//Functions for shape creation
void MakePoint(std::shared_ptr<CAD::Point>);
template <std::size_t ... Is>
std::tuple<Shapes...> CreateShapeTuple(std::index_sequence<Is...>)
{
std::tuple<Shapes...> res;
(MakePoint(std::get<Is>(res)), ...); // C++17
/* or C++11
const int dummy[] = {0, (MakePoint(std::get<Is>(res)), 0)...};
static_cast<void>(dummy); // Avoid warning for unused variable.
*/
return res;
}
public:
//Create Object Function
std::tuple<Shapes...> CreateShapeTuple() {
return CreateShapeTuple(std::index_sequence_for<Shapes...>());
}
};
Upvotes: 1