Я хочу разработать типобезопасное кросс-соединение NxM. Это механизм, который позволяет подключить любой из N функциональных выходов к любому из M входов. Или, другими словами, связать возвращаемое значение функции (из набора функций) с параметром другого. Ключевым аспектом является то, что эти соединения должны настраиваться во время выполнения. Основная проблема, с которой я столкнулся, заключается в том, что тип входов будет отличаться от выходов в зависимости от каждого соединения.
Скажем, в какой-то произвольный момент в программе я хочу связать возвращаемое значение float foo()
с параметром val
в void bar(double val)
.
В настоящее время у меня есть два параметризованных класса, представляющих входы и выходы, с именами Source<T>
и Dest<U>
. Ожидается, что T & U будет float, double, bool, int, unsigned int и т. Д. У меня есть гетерогенная коллекция из Source<T>
экземпляров, некоторые из них double, некоторые float, некоторые int, некоторые bool. Существует также разнородная коллекция Dest<U>
экземпляров, а также несколько экземпляров типа double, некоторые с плавающей запятой, некоторые int, некоторые bool. Иногда T и U одного типа. Для большего контекста все эти экземпляры связаны с уникальными именами, что позволяет системе более высокого уровня сказать «теперь, пожалуйста, соедините source :: foo с dest :: bar» или «удалите связь между source :: red и dest :: blue. ".
В предыдущем примере во время компиляции тип возвращаемого значения из foo()
известен программисту как float и может быть указан в исходном коде, поэтому Source<float>
можно создать и связать с этой функцией. И тип параметра для bar()
также известен как двойной, поэтому Dest<double>
может быть создан и связан с этой функцией (с оболочкой std::function
). Затем во время выполнения Source<float>
можно связать с Dest<double>
и передать значение Dest<double>
через полиморфный указатель (через унаследованный интерфейс, общий для всех Dest<U>
экземпляров). Dest<double>
затем вызовет функцию bar()
, используя std::function
оболочку.
Итак, во время выполнения цель состоит в том, чтобы связать любой Source
с любым Dest
на произвольную продолжительность и повторно связать в любое время. Поэтому мне нужен способ создать функцию, которая может преобразовывать тип T
, известный только во время выполнения, в другой тип U
, который также известен только во время выполнения.
Чтобы немного усложнить ситуацию, возвращаемые значения и значения параметров могут быть массивами произвольного размера. Например, foo()
может возвращать массив float[32]
, но bar()
может ожидать массив double[8]
(возможно, отбрасывая 3 из каждых 4 значений). Я считаю, что этот механизм «Мост» справится с этим, как только он сможет справиться с преобразованием типа.
Честно говоря, я не очень понимаю, как это реализовать. Если бы ассоциации Source-to-Dest были исправлены во время компиляции, я мог бы написать семейство шаблонных Bridge<T,U>
функций, которые выполняли бы преобразование, но поскольку все это должно происходить во время выполнения, я не думаю, что это ответ.
Это лучший подход - написать общую Bridge<T,U>
функцию, а затем создать какой-то механизм динамической диспетчеризации для выбора подходящего во время выполнения на основе T и U? Как мне определить типы T и U во время выполнения, чтобы выбрать правильный экземпляр Bridge
? Я также хотел бы уловить случай, когда T и U являются одним и тем же типом, и, следовательно, избежать ненужного преобразования (в качестве оптимизации).
Или есть лучший способ добиться того, что я хочу делать?
Egg
, который преобразуется вChicken
. Некоторые вопросы: можно ли перечислить все типы ввода и вывода? Можете ли вы выполнить сериализацию в оба конца? Можете ли вы написать шаблонный код для каждого типа, который вы добавляете в систему? (то есть, прежде чем вы сможете добавить типT
какDest<T>
, вы должны где-нибудь зарегистрировать типT
). Может ли эта регистрация быть детерминированной во время компиляции? Или вы добавляете сторонние библиотеки DLL с их собственными пользовательскими функциями, которые производятDest<Egg>
иSource<Chicken>
? - person Yakk - Adam Nevraumont   schedule 25.03.2013double
, а затем std :: function должна обработать преобразование до float, int и т. Д. При вызове последней функции. Не помогает с 64-битными целыми числами, но я все равно не планирую их использовать. - person davidA   schedule 25.03.2013