Re[2]: Вопрос по идентификации типа (не RTTI)
От: niralex  
Дата: 08.04.19 20:22
Оценка:
Здравствуйте, niXman, Вы писали:

X>такое нагуглилось: https://github.com/Neargye/nameof


X>насколько я понял, твой случай это использовать макрос NAMEOF_RAW()(https://github.com/Neargye/nameof#remarks), и к результату применить какоу-нить compile-time hash.


Интересная библиотечка, спасибо! А как быть с псевдонимами, пространствами имен, например может быть такое:
using MyAlias = MyType;


и тогда MyAlias и MyType разные типы?

или
MySpace::MyType и MyType(с предварительным using namespace MySpace) тоже разные?
Re[3]: Вопрос по идентификации типа (не RTTI)
От: Erop Россия  
Дата: 09.04.19 04:01
Оценка:
Здравствуйте, niralex, Вы писали:

N>Объекты инстанцируются в разных динамических модулях/процессах, используются разные компиляторы, поэтому эти адреса будут отличаться. Если бы все было в одном модуле то хватило бы стандартного RTTI


IMHO в этом месте надо подробнее рассказать сценарий того, что хочется делать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Вопрос по идентификации типа (не RTTI)
От: rg45 СССР  
Дата: 09.04.19 05:15
Оценка:
Здравствуйте, niralex, Вы писали:

N>С fold expressions знаком. Вопрос как раз в "способе комбинирования". Слишком большое число комбинаций. Например для 15 типов это 15!=1307674368000 комбинаций. А еще типы подобные array<n, TMyType>, где в идентификаторе типа нужно учитывать n типа size_t.


Возможно, нужно просто проанализировать реальные потребности и на их основе ввести какие-то разумные ограничения в модель? Что-то мне подсказывает, что общее количество типов в программе, включая все воплощения шаблонных классов, будет существенно скромнее астрономических чисел.
--
Отредактировано 09.04.2019 5:47 rg45 . Предыдущая версия .
Re[4]: Вопрос по идентификации типа (не RTTI)
От: niralex  
Дата: 09.04.19 08:05
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, niralex, Вы писали:


N>>Объекты инстанцируются в разных динамических модулях/процессах, используются разные компиляторы, поэтому эти адреса будут отличаться. Если бы все было в одном модуле то хватило бы стандартного RTTI


E>IMHO в этом месте надо подробнее рассказать сценарий того, что хочется делать...


Попробую описать сценарий... Реализуеся универсальный механизм связывания для делегатов:

Если делегат и вызываемая сщность находятся в одном модуле, связывание и передача параметров происходят стандартным образом, но если в разных, параметры проходят процедуру кодирования/декодирования (для согласования форматов представления данных, потокобезопасности и др.) Обработка выполняется кодерами/декодерами, которые реализованы как множество типов, включающих статические методы Encode/Decode.
Например:

// ---Модуль main---
/* Создание делегата с двумя параметрами, для кодирования которых используются void IntCodec::Encode(std::byte *buffer, int Value) и void StringCodec::Encode(std::byte *buffer, string Value) */
MyDelegate<IntCodec, StringCodec> d; 

/* Делегат может быть связан с вызываемыми сущностями, которые предварительно должны быть зарегистрированы */
// Создание вызываемых сущностей
Callee f1 = LocalFunction<IntCodec, StringCodec>(func); // func - локальная функция с сигнатурой func(int, char)
Callee f2 = GetFromDll("libname", index); // index - номер функции, которая зарегистрирвоана в dll
Callee f3 = GetRemoteFunction("url", index); // index - номер функции, которая зарегистрирвоана на удаленном узле

d.Bind(f1); // связывание с локальной функцией
d(1, "direct call == std::funcion()"); // вызов
d.Bind(f2); // связывание с функцией из DLL
d(2, "Call with encoding/decoding"); // вызов
d.Bind(f3); // связывание с удаленной функцией
d(3, "Remote call with encoding/decoding"); // вызов

// ---Модуль DLL---
int index = RegisterFunction<IntCodec, StringCodec>(func); // func - внутренняя функция dll

// ---Remote module---
int index = RegisterFunction<IntCodec, StringCodec>(func); // func - внутренняя функция dll


Сценарий такой: функции LocalFunction, GetFromDll и GetRemoteFunction получают информацию о типах кодеров/декодеров для вызываемой сущности из параметров шаблона, из dll или от удаленного узла, а функция Bind проверяет соответствие этих типов. Вот именно для этого и нужно идентифицировать типы и передавать идентификаторы. Поскольку вызовы Bind происходят часто, хочется чтобы идентификация проходила на этапе компиляции (само сравнение, естественно происходит в рантайме).
Re[6]: Вопрос по идентификации типа (не RTTI)
От: niralex  
Дата: 09.04.19 08:23
Оценка: 1 (1)
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, niralex, Вы писали:


N>>С fold expressions знаком. Вопрос как раз в "способе комбинирования". Слишком большое число комбинаций. Например для 15 типов это 15!=1307674368000 комбинаций. А еще типы подобные array<n, TMyType>, где в идентификаторе типа нужно учитывать n типа size_t.


R>Возможно, нужно просто проанализировать реальные потребности и на их основе ввести какие-то разумные ограничения в модель? Что-то мне подсказывает, что общее количество типов в программе, включая все воплощения шаблонных классов, будет существенно скромнее астрономических чисел.


Это будет библиотека в которой комбинировать типы будут пользователи и проанализировать их потребности сложно. Хотя, конечно основным пользователем буду я сам но, все-таки, не хочется себя ограничивать . Проект преследует помимо прочего, учебные цели, так как программированием профессионально не занимаюсь. Отсюда, возможно некий перфекционизм.
Re[7]: Вопрос по идентификации типа (не RTTI)
От: rg45 СССР  
Дата: 09.04.19 08:31
Оценка:
Здравствуйте, niralex, Вы писали:

N>Это будет библиотека в которой комбинировать типы будут пользователи и проанализировать их потребности сложно. Хотя, конечно основным пользователем буду я сам но, все-таки, не хочется себя ограничивать . Проект преследует помимо прочего, учебные цели, так как программированием профессионально не занимаюсь. Отсюда, возможно некий перфекционизм.


Ах, как я тебя понимаю. Я и сам всю жизнь пытаюсь изобрести супер-универсальный всемогутор. А заканчивается всегда тем, что локальное специализированное решение оказывается более выигрышным и жизнеспособным, чем универсальное.
--
Re[5]: Вопрос по идентификации типа (не RTTI)
От: Erop Россия  
Дата: 11.04.19 10:52
Оценка: 1 (1)
Здравствуйте, niralex, Вы писали:

N>Сценарий такой: функции LocalFunction, GetFromDll и GetRemoteFunction получают информацию о типах кодеров/декодеров для вызываемой сущности из параметров шаблона, из dll или от удаленного узла, а функция Bind проверяет соответствие этих типов. Вот именно для этого и нужно идентифицировать типы и передавать идентификаторы. Поскольку вызовы Bind происходят часто, хочется чтобы идентификация проходила на этапе компиляции (само сравнение, естественно происходит в рантайме).



Если я верно понял, у модулей всё равно есть какая-то подготовка. То есть мы не имеем какой-то API более или менее родной для каждой dll, а включаем в dll наш код для маршелинга. Так?


В любом случае нам нужно обеспечить две вещи.

1) Логическую совместимость вызывающей и вызываемой стороны. Тут должны быть какие-то правила, автоматически или полуавтоматически выводимые. Ну, например, можно ли наследника передавать вместо базы. И т. д.

2) Бинарную совместимость в случае, если (1) есть, но по разные стороны имеются разные языки/среды разработки и т. д.


Казалось бы, бы всегда можем использовать уникальные id всех сущностей, а в RT строить табличку что с чем совместимо с т. з. (1), и, соответственно, что надо использовать для (2)


Правда, если отказаться от идеи, что мы не делаем промежуточный модуль совместимости, а, наоборот, по API dll какой-то тулзой генерить переходную lib, то можно сделать генерилки для N платформ, переходников из каждой в каждую.

При загрузке/финальной сборке будут выбираться правильные версии этих интерфейсов и всё решится само собой во время загрузки приложения...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Отредактировано 13.04.2019 9:57 Erop . Предыдущая версия .
Re[6]: Вопрос по идентификации типа (не RTTI)
От: niralex  
Дата: 12.04.19 05:40
Оценка:
Здравствуйте, Erop, Вы писали:

E>Если я верно понял, у модулей всё равно есть какая-то подготовка. То есть мы не имеем какой-то API более или менее родной для каждой dll, а включаем в dll наш код для маршелинга. Так?


Да, в dll есть код, который позволяет получить метаинформацию о функциях: уникальный идентификатор функции и типы кодеров для их параметров.
Основная программа использует только эту информацию для связывания и вызова функций из dll, т.е. она не обращается к самой функции, а передает в dll идентификатор функции и параметры в закодированном виде.

E>В любом случае нам нужно обеспечить две вещи.


E>1) Логическую совместимость вызывающей и вызываемой стороны. Тут должны быть какие-то правила, автоматически или полуавтоматически выводимые. Ну, например, можно ли наследника передавать вместо базы. И т. д.


Я понимаю под логической совместимостью количество, порядок следования и тип параметров и тип возвращаемого значения.

E>2) Бинарную совместимость в случае, если (1) есть, но по разные стороны имеются разные языки/среды разработки и т. д.


Да. Для этого используются кодеры/декодеры для стандартных и пользовательских типов и специфицированный бинарный формат.

E>Казалось бы, бы всегда можем использовать уникальные id всех сущностей, а в RT строить табличку что с чем совместимо с т. з. (1), и, соответственно, что надо использовать для (2)

E>Правда, если отказаться от идеи, что мы не делаем промежуточный модуль совместимости, а, наоборот, по API dll какой-то тулзой генерить переходную lib, то можно сделать генерилки для N платформ, переходников из каждой в каждую.
E>При загрузке/финальной сборке будут выбираться правильные версии этих интерфейсов и всё решится само собой во время загрузки приложения...

Не совсем понял... Dll подгружаются/выгружаются динамически, связывание вызывающей сущности в основной программе с функцией в dll(или на удаленном сервере) должно быть в run-time. Как тут помогут "переходные lib"?

По своему вопросу нашел одну идею. Привожу ниже.
Re: Вопрос по идентификации типа (не RTTI)
От: niralex  
Дата: 12.04.19 05:50
Оценка: 1 (1)
Нашел идею решения своего первоначального вопроса. Может кому-то понадобится...

N>Есть некий конечный набор пользовательских типов и задача их идентифицировать во время выполнения не используя RTTI.

N>Тип идентификатора не важен. Варианты без constexpr известны.

В качестве идентификатора типа берем std::array.
Для шаблонных типов делаем constexpr-конкатенацию array

// Реализацию функции join берем отсюда(спасибо автору Klemens Morgenstern): https://gist.github.com/klemens-morgenstern/b75599292667a4f53007
template<typename T, std::size_t L, std::size_t R>
constexpr std::array<T, L+R> join(std::array<T, L> rhs, std::array<T, R> lhs) {...};

struct IntCodec
{
    static constexpr auto Id() { return array<int8_t,1>{1}; }
    // ...
};

struct CharCodec
{
    static constexpr auto Id() { return array<int8_t,1>{2}; }
    // ...
};

template<typename T>
struct VectorCodec
{
    static constexpr auto Id() 
    { 
        return join(array<int8_t,1>{3}, T::Id());  
    }
    // ...
};

int main()
{
    constexpr auto id1 = IntCodec::Id();  // 1
    constexpr auto id1 = VectorCodec<CharCodec>::Id(); // 3,2
    constexpr auto id2 = VectorCodec<VectorCodec<IntCodec>>::Id(); // 3,3,1
    return 0;
}

В результате идентификация типов происходит в compile-time! Мелочь, но приятная
Идентификаторы затем можно сериализовывать, передавать между модулями, сравнивать и т.д.
Буду благодарен, если кто укажет на ошибки, потенциальные проблемы, предложит улучшения, альтернативы.


P.s.
Небольшие косметические улучшения:
Написал функцию MakeTypeId(1), чтобы вместо return array<int8_t,1>{1} писать MakeTypeId(1);
template <typename... Types>
constexpr auto MakeTypeId(Types&&... t)
{
    return std::array<int8_t, sizeof...(Types)>{ std::forward<Types>(t)... };
}


И написал более компактную функцию join, которую можно использовать для объединения не двух, а любого числа array:
template<typename... TArrs>
constexpr auto join(const TArrs&... arrs)
{
    std::size_t i = 0;
    std::array<int8_t, (arrs.size() + ...)> ret{};
    ([&](const auto& arr)
     {
        for (const int8_t& val : arr)
            ret[i++] = val;
     }(arrs), ...);
    return ret;
}
Отредактировано 12.04.2019 7:40 niralex . Предыдущая версия . Еще …
Отредактировано 12.04.2019 6:34 niralex . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.