Практика разработки языка программирования, как скомпилировать интерфейсы в стиле golang для c ++? - PullRequest
3 голосов
/ 10 апреля 2020

Ради интереса я работаю над собственным языком программирования, который компилируется в C ++. Хотя большинство вещей довольно просто напечатать, у меня возникли проблемы при компиляции моих интерфейсов в стиле golang для c ++. В golang вам не нужно явно объявлять, что конкретная структура реализует интерфейс, это происходит автоматически, если в структуре есть все функции, объявленные в интерфейсе. Первоначально я собирался скомпилировать интерфейсы до класса со всеми виртуальными методами, например

class MyInterface {
    public:
        void DoSomthing() = 0;
}

, и все реализующие структуры просто вышли бы из интерфейса, как вы это обычно делаете в c ++

class MyClass: public MyInterface {
    // ...
}

Однако это будет означать, что мой компилятор должен будет l oop для каждого интерфейса, определенного в исходном коде (и всех зависимостей), а также для каждой структуры, определенной в источнике, и проверить, реализует ли структура интерфейс, используя операцию, которая займет O (N * M) время, где N - это число структур, а M - количество интерфейсов. Я провел некоторый поиск и наткнулся на некоторый код на C ++: http://wall.org/~lewis/2012/07/23/go-style-interfaces-in-cpp.html, который делает интерфейсы стиля golang в c ++ реальностью, и в этом случае я мог бы просто скомпилировать свои интерфейсы для кода, похожего на этот (хотя и не совсем так как я не решаюсь использовать необработанные указатели над умными указателями), и мне не нужно беспокоиться об их явной реализации. Однако автор заявляет, что этого нельзя делать для производственного кода, что меня немного беспокоит.

Это довольно загруженный вопрос, который может быть немного субъективным, но может ли кто-нибудь с большим знанием C ++ сказать мне, если это так, как предложено в статье, действительно плохая идея, или это на самом деле не так уж плохо и может быть сделано, или если есть лучший способ написать код на C ++, который позволил бы мне достичь желаемого поведения, не прибегая к O (N * M) l oop?

1 Ответ

0 голосов
/ 10 апреля 2020

Моя первоначальная мысль - использовать тот факт, что C ++ поддерживает множественное наследование. Разложите ваш golang интерфейс на однофункциональные интерфейсы. Ха sh все интерфейсы по своей уникальной подписи. Теперь он становится операцией O (N), чтобы найти набор абстрактных интерфейсов C ++ для ваших конкретных классов.

Аналогично, когда вы потребляете объект, вы находите все использованные интерфейсы. Теперь это O (M) по той же логике c. Общая сложность компилятора становится O (N) + O (M) вместо O (N * M).

Небольшой недостаток в том, что у вас будет O (N) vtables в C ++. Некоторые из них могут быть объединены, если определенные интерфейсы всегда группируются вместе.

...