Должны ли сторонние типы быть представлены в API моей библиотеки C++

Я разрабатываю библиотеку C++, где пользователь будет предоставлять сложные входные данные, такие как матрицы и кватернионы. Я не хочу переопределять эти типы, так что внутри я буду использовать библиотеку Eigen.

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

1) Используйте только основные типы C++

Эта опция потребует от клиентов передачи данных через базовые типы. Например, для передачи кватерниона (4 элемента) можно сделать:

void my_func(double my_quat[4])

2) Раскрыть типы Эйгена

Eigen предоставляет несколько шаблонных типов для массивов и кватернионов. Например, если функция требует кватерниона, я мог бы использовать Эйгена Quaterniond тип (который на самом деле является typedef для Quaternion<double>):

void my_func(const Eigen::Quaterniond& my_quat)

3) Создать простую обертку для различных типов для клиентов

Я мог бы создать очень простой тип кватерниона (скажем, некоторую простую структуру), который клиенты должны были бы создать (возможно, через какую-то фабричную функцию) для передачи моему API:

void my_func(const quaternion_t& my_quat)

Моя библиотека будет конвертировать quaternion_t введите мое внутреннее представление Eigen.

Мне не очень нравится вариант 1, так как я хочу, чтобы в моих API было больше ощущения при наборе текста. Вариант 2 потребует от моих клиентов также использовать Eigen, не говоря уже о потенциальных проблемах с совместимостью, если они используют другую версию Eigen (кстати, Eigen - это библиотека только для заголовков, если это имеет значение). Это оставляет вариант 3.

Что думают люди? Я в основном ответил на свой вопрос? Есть какие-нибудь примеры?

Смежные вопросы

Здесь был задан связанный вопрос, но он не вдавался в подробности того, следует ли выставлять внешние типы.

2 ответа

Решение

Оберните / инкапсулируйте. Допустим, вы хотите добавить некоторые дополнительные функции, такие как кэширование результатов вычислений, например, нормы кватерниона, в качестве изменения реализации. Вы не можете сделать это (так легко), если вы выставляете сторонние типы, не вынуждая свой клиентский код изменять свой вызов.

Раскрытие сторонних библиотек является самым легким в краткосрочной перспективе, но, скорее всего, в долгосрочной перспективе укусит вас в спину. Проще всего, потому что типы находятся там, вам не нужно придумывать свои собственные. Укусит вас, если вы захотите использовать другую библиотеку реализации в будущем, или захотите разрешить расширение данных, которые клиент передает вам.

Использование только базовых типов - это почти то же самое, что придумать свой собственный, но это гораздо более низкий уровень, без веской причины. Вашим пользователям будет трудно использовать вашу библиотеку, не обращаясь к документации о том, что к чему.

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

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

Другие вопросы по тегам