Автоматическая сортировка #include зависимостей в C ++ - PullRequest
1 голос
/ 31 декабря 2010

У меня есть некоторый код, происходящий из DSL, который нужно перевести для вызывающей стороны C ++. Мне нужно выяснить, как сортировать зависимости #include в C ++. К счастью, у меня есть несколько ограничений, которые могут облегчить мою задачу:

  1. Результат не содержит шаблонов или макросов. Я могу использовать шаблоны или макросы, чтобы облегчить мне жизнь, но DSL явно не генерирует ничего, что требует их - вся предварительная обработка, с этой целью позаботились о генерации кода.
  2. Полученный код вовсе не обязательно должен быть читаемым или обслуживаемым - он будет создаваться и потребляться программой. Желательно, чтобы это не повлекло за собой ухудшение производительности или не запутало оптимизаторы, но я могу жить, если придется.

Однако мне нужно преобразовать некоторый код, который описывает программы, которые являются допустимыми для C ++, но не могут быть определены, например,

struct X {
    Y y;
    Y func();
};
struct Y {
    X func();
};
// or
struct Y {
    void func(X x);
};
struct X {
    void func(Y y);
};

Пока что мне пришла в голову мысль, что я бы сделал каждый тип отдельным независимым заголовком, а затем в файле реализации я могу просто #include все типы, от которых зависит реализация, что не будет слишком сложно. Вопрос в том, как я могу изменить код X и Y, чтобы это было возможно.

Прямо сейчас, я подумал о применении RVO и NRVO и о чем-то похожем на аргументы. Но разве бывают случаи, когда они не просто не оптимизированы, но на самом деле невозможны? Это написано в MSVC10, поэтому я могу справиться с любыми дополнительными функциями, которые C ++ 0x может предложить здесь.

Редактировать: я отредактировал свой код, потому что я немного занизил свои потребности. RVO и NRVO также не могут сократить это.

Edit edit: Я предполагаю, что, если предварительных объявлений будет достаточно для возвращаемых значений функции и аргументов, я мог бы топологически отсортировать по порядку включения элементов данных. В конце концов, все еще не разрешено делать что-то вроде

struct X {
    Y y;
};
struct Y {
    X x;
};

Ответы [ 3 ]

1 голос
/ 31 декабря 2010

Топологическая сортировка - путь.

Если это не сработает, вам нужно преобразовать код с помощью shared_ptr или что-то, что ослабляет ограничения порядка.

1 голос
/ 31 декабря 2010

Почему бы не использовать предварительные объявления?

Ваш пример вполне подходит, если вы объявите X и Y таким образом:

struct Y;
struct X {
    Y func();
};
struct Y {
    X func();
};

Вы можете поместить каждое объявление типа в свой собственный заголовок, предварительно добавивэто путем предварительных объявлений каждого типа, используемого в объявлении, а затем в файле реализации включает все заголовки используемых типов.Если вы пересылаете все типы, используемые в объявлении типа, вам больше не нужно беспокоиться о том, какой файл включить первым.Неважно.

Подводя итог:

headerA.h

#pragma once
class B;

class A {
    B b;
public:
    void myfunc();
};

headerB.h

#pragma once
class A;

class B {
    A a;
};

implA.cpp

#include "headerA.h"
#include "headerB.h"

void A::myfunc() {
    // ...
}

Таким образом, при использовании типа A в несвязанном коде, вы должны включить как headerA.h, так и headerB.h.Если вы просто хотите включить headerA.h при использовании типа A, отрегулируйте заголовки следующим образом:

headerA.h

#pragma once
class B;
#include "headerB.h"

class A {
    B b;
public:
    void myfunc();
};

headerB.h

#pragma once
class A;
#include "headerA.h"

class B {
    A a;
};

Охрана включения позаботится обо всем остальном.

0 голосов
/ 31 декабря 2010

передайте аргументы по адресу или создайте промежуточный тип данных, который не зависит от X или Y, и передайте его. Вы действительно не можете избежать проблем возврата / передачи по значению, потому что размер / интерфейсы недоступны. как есть, они взаимозависимы.

Полагаю, другой вариант - объявить их обоих в одном интерфейсе класса.

вы могли бы использовать шаблоны и специализации ... но это, вероятно, будет сложно поддерживать, если вы не хотите писать определения, а генератор предоставляет опцию для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...