циклическая ссылка — компиляция C ++ отношения многих ко многим классам

Я хочу знать, как добиться следующего дизайна. Я не приложил усилий, чтобы следовать стандартным соглашениям, чтобы свести этот фиктивный код к минимуму (например, включить охрану). Для аргументов я использую C ++ 03 и только стандартные компоненты библиотеки.

TL; DR: Есть циклическая зависимость между моим Restaurant а также Recipe классы. у меня есть std::set<> одного из указателей на объект Recipe в Restaurant класс и наоборот. Я не могу #include один в другом, но из-за предварительного объявления компилятор не позволяет мне объявлять пользовательский компаратор для коллекций, так как value_typeна тот момент это еще неполные типы. Есть ли способ добиться этого?

Я включил в код комментарии, которые объясняют мою проблему более подробно.

/*
* restaurant.h
*/
#include <string>
#include <set>
/*
* I cannot do this as recipe.h would need to include
* restaurant.h, which restricts
* me when I want to write a custom comparator.
*/
// #include "recipe.h"
class Recipe;

// I know this will not work as Recipe has not yet been declared.
struct RecipeComparator {
bool operator() (const Recipe* lhs, const Recipe* rhs) {
return lhs->price() < rhs->price();
}
};

class Restaurant {
public:
Restaurant(const std::string& name, float averagePrice);
float averagePrice() { return m_averagePrice; }

private:
std::string m_name;
float m_averagePrice;
/*
* I want to have the recipies sorted by their prices.
* I cannot define RecipeComparator here as Restaurant
* is an incomplete type till now.
*/
std::set< Recipe*, RecipeComparator > m_recipiesSorted;

/*
* This works, but does not do what I want.
*/
std::set< Recipe* > m_recipies;
};

/*
* recipe.h
*/
#include <string>
#include <set>
/*
* I cannot do this as restaurant.h would need to include
* recipe.h, so I need to forward declare, which restricts
* me when I want to write a custom comparator.
*/
// #include "restaurant.h"
class Restaurant;

// I know this will not work as Restaurant has not yet been declared.
struct RestaurantComparator {
bool operator() (const Restaurant* lhs, const Restaurant* rhs) {
return lhs->averagePrice() < rhs->averagePrice();
}
};

class Recipe {
public:
Recipe(const std::string& name, float price);
float price() { return m_price; }

private:
std::string m_name;
float m_price;
/*
* This is what I want as I want to have the restaurants sorted
* by their average prices.
* I cannot define RestaurantComparator here as Restaurant
* is an incomplete type till now.
*/
std::set< Restaurant*, RestaurantComparator > m_restaurantsSorted;

/*
* This works, but does not do what I want.
*/
std::set< Restaurant* > m_restaurants;

};

2

Решение

Одна идея состоит в том, чтобы переместить ваши определения Comparator в источник .cpp, сохраняя объявления в заголовке. Сюда, restaurant.h а также recipe.h будет по-прежнему ссылаться друг на друга только по имени, поэтому будет достаточно предварительного объявления.

// restaurant_recipe_comparators.h
// probably too long, give it a better name
struct RestaurantComparator
{
bool operator() (const Restaurant *, const Restaurant *);
};

struct RecipeComparator
{
bool operator() (const Recipe *, const Recipe *);
};

// restaurant_recipe_comparators.cpp
bool RestaurantComparator::operator() (const Restaurant* lhs, const Restaurant* rhs)
{
return lhs->averagePrice() < rhs->averagePrice();
}bool RecipeComparator::operator() (const Recipe* lhs, const Recipe* rhs)
{
return lhs->price() < rhs->price();
}
4

Другие решения

Других решений пока нет …