/ru_c++

Home | Settings | Delete | Help
О C++ на русском.


10/09/2023 22:16 Thread №52 Posts: 10 [Open thread] [Delete]

std::variant vs наследование

std::variant vs наследование

В последнее время предпочитаю использовать std::variant, а не наследование, когда мне нужен тип-сумма.

Но бывают ситуации, когда из-за std::variant ходишь по тонкому льду.

Например, хочу создать типы данных для описания выражений в языке программирования:
hidden posts: 5
10/09/2023 22:28 Post №249

/**
 * Helper function to access a nested child by path.
 */
const TemplateItem &getDeepChild(const TemplateItem &root,
                                 const std::vector<std::string> &path);

/**
 * Object template item. It doesn't have a value and has children accessible by
 * names.
 */
class Object : public TemplateItem {
public:
  using InitializerList = std::initializer_list<
      std::pair<const std::string, std::shared_ptr<TemplateItem>>>;
  using Map = std::map<std::string, std::shared_ptr<TemplateItem>>;

public:
  Object(InitializerList data);
  Object(const Map &data);
  Object(Map &&data);
  const TemplateItem &child(const std::string &name) const;
  std::string value() const;
  iterator begin();
  iterator end();
  const_iterator begin() const;
  const_iterator end() const;

private:
  std::map<std::string, std::shared_ptr<TemplateItem>> data;
};

10/09/2023 22:29 Post №250

/**
 * Array template item. It doesn't have a value and has childern accessible as
 * an array.
 */
class Array : public TemplateItem {
public:
  using InitializerList = std::initializer_list<std::shared_ptr<TemplateItem>>;
  using Vector = std::vector<std::shared_ptr<TemplateItem>>;

public:
  Array(InitializerList data);
  Array(const Vector &data);
  Array(Vector &&data);
  const TemplateItem &child(const std::string &name) const;
  std::string value() const;
  iterator begin();
  iterator end();
  const_iterator begin() const;
  const_iterator end() const;

private:
  Vector data;
};

10/09/2023 22:30 Post №251
Когда использую наследование, почти всегда прихожу к необходимости использовать std::shared_ptr.
11/09/2023 18:23 Post №254
>>245
>Expression - это вектор, скаляр, имя переменной или вызов функции. А FunctionCall (вызов функции) содержит вектор из Expression.
Хорошо бы пояснить на примере конкретной задачи, где такое может оказаться полезным.
11/09/2023 23:19 Post №258
>>254
>Хорошо бы пояснить на примере конкретной задачи, где такое может оказаться полезным.
На кислице был мой тред про софтовый рендеринг. Сделал такой формат описания моделей:

{
	"dots": {
		"house.a0": [-30, 0, -10],
		"house.b0": [-20, 0, -10],
		"house.c0": [-20, 0, -16],
		"house.a1": [-30, 3, -10],
		"house.b1": [-20, 3, -10],
		"house.c1": [-20, 3, -16],
		...
	},
	"lines": [
		["house.a0", "house.b0", "house.c0"],
		["house.a1", "house.b1", "house.c1"],
		["house.a0", "house.a1"],
		...
	]
}

Тут рисуются контуры 3 стен дома. Неудобно. Чтобы его повернуть или передвинуть, надо менять координаты всех точек. А там еще есть окна и дверь.
Хочу, чтобы можно было задать 1 точку и 3 вектора, а остальное описать формулами:

{
	"vars": {
		"house.base": [-30, 0, -10],
		"house.size_a": [10, 0, 0],
		"house.size_b": [0, 0, -6],
		"house.size_c": [0, 3, 0],
		
		"house.dot.a": ["sum", "house.base", "house.size_a"],
		"house.dot.b": ["sum", "house.base", "house.size_b"],
		"house.dot.c": ["sum", "house.base", "house.size_c"],
		...
		"window.dot.a": ["sum", "house.base", ["mul", "house.size_a", 0.25], ["mul", "house.size_c", 0.25]],
		...
	},
        ...
}