2012-05-14 2 views
5

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

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

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

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

void my_func(double my_quat[4]) 

2) Expose Типы Эйген в

Эйген предоставляет несколько калиброванных типов для массивов и кватернионов. Для Например, если функция требует кватерниона, я мог бы использовать Эйген в Quaterniond типе (который на самом деле является ЬурейиМ для 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.

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

Вопросы, относящиеся

Смежный вопрос был задан here, но на самом деле не вдаваться в подробности, следует ли один выставить внешние типы.

+0

Как насчет опции 3, с конструкторами, которые принимают оба варианта 1 и 2? Семантика C++ позволяет вам перенаправлять типы объявлений достаточно хорошо, чтобы это работало (клиенты без Eigen могут по-прежнему включать заголовок и не работать во время компиляции). – Lalaland

+0

Я думал о чем-то подобном, но, я думаю, я немного неясен в том, как пересылать объявить типы шаблонов typedef'd, хотя, я думаю, в моем случае я, вероятно, ограничу клиентов передачей определенного экземпляра типов (как 'Quaternion ' в отличие от 'Quaternion '). – plasma

+0

Я также немного расплывчатый о том, что произойдет, если клиент использует конструктор, чтобы сделать тип моей библиотеки с их Eigen-типом, но они используют другую версию Eigen, которая может, скажем, иметь небольшое изменение в реализации. – plasma

ответ

2

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

+0

Согласен. Тем не менее, я не обязательно хочу разоблачить всю матрицу/кватернион/и т. Д. из моей собственной библиотеки, поскольку функциональность моей библиотеки будет на более высоком уровне. Было бы целесообразно, чтобы мои классы-обертки предлагали минимальную функциональность для связи с моим API и позволяли клиентам использовать то, что они хотят для фактического управления данными, связанными с этими типами? – plasma

+0

Тонкие обертки в порядке. my_quaternion :: foo() {return their_quaternion.foo(); } отлично подходит для функций, которые вы хотите открыть. Как отметил @Attila, наиболее драматичным случаем является тот, в котором вы хотите сменить библиотеки, с которыми не должен справиться ваш клиент. Если вы считаете, что клиентам нужен сверхпрочный доступ к полноценным математическим объектам от собственного: также предлагайте функцию преобразования getEigen() и ctor, которая берет на себя в качестве входных данных, чтобы идти туда и сюда, что вы гарантируете, всегда будет работать даже если вы повторно реализуете в другой библиотеке. – djechlin

+0

Что произойдет, если клиент, использующий функцию ctor или getEigen() и мою библиотеку, будет скомпилирован с различными версиями Eigen? Я предполагаю, что если обе версии совместимы с ABI, тогда мы хорошие. Но если что-то изменится, разве это не сработает? В частности, я думаю о случае, когда я предоставляю свою библиотеку как DSO, но, я думаю, я не знаю, что произойдет, если я дам клиентам статическую библиотеку. – plasma

2

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

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

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

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