Понадобилось нечто сходное com-овскому IID: с более простым требованием, что классу сопоставляется некоторое уникальное число в пределах compilation unit.
Мне нужно сходное, причем можно даже если для такого рода классов forward declaration сделаны в одном и том же файле.
Самое простое, что можно придумать в части такого сопоставления вероятно выглядит как просто определение некоторого уникального MyRealID прямо в теле класса. В этом случае не нравится:
требование включать определение класса туда, где достаточно только знать class ID
слишком ручной способ определения значения id
Чуть сложнее:
// classids.htemplate<class T>
struct ID {};
class SomeClass1;
template<>
struct ID<SomeClass1> {
static const int Value = 1; // be careful to avoid duplicate IDs
};
class SomeClass2;
template<>
struct ID<SomeClass2> {
static const int Value = 2; // be careful to avoid duplicate IDs
};
// someclass1.hclass SomeClass1 {
public:
static const int MyRealID = ID<SomeClass1>::Value;
};
// someclass2.hclass SomeClass2 {
public:
static const int MyRealID = ID<SomeClass2>::Value;
};
в этом случае "uuidof" примерно эквивалентен записи SomeClass1::MyRealID либо ID<SomeClass1>::Value для последнего достаточно включения classids.h без включения самого определения класса someclass1.h
Можно ли сделать чуть более элегантнее и/ли проще? В последнем случае можно было бы вероятно использовать compile time counter, который проскальзывал на rsdn сколько-то лет назад, не уверен есть ли какая-то стандартная альтернатива.
Здравствуйте, A13x, Вы писали:
A>Понадобилось нечто сходное com-овскому IID: с более простым требованием, что классу сопоставляется некоторое уникальное число в пределах compilation unit.
А как насчёт C++ RTTI?
Функция typeid().hash_code вернёт уникальный цифровой код для класса.
Здравствуйте, A13x, Вы писали:
A>Понадобилось нечто сходное com-овскому IID: с более простым требованием, что классу сопоставляется некоторое уникальное число в пределах compilation unit.
Здравствуйте, Maniacal, Вы писали:
M>Здравствуйте, A13x, Вы писали:
M>А как насчёт C++ RTTI? M>Функция typeid().hash_code вернёт уникальный цифровой код для класса.
hash_code же не уникальный. По той же ссылке:
No other guarantees are given: std::type_info objects referring to different types may have the same hash code
Re[2]: Сопоставление классу уникального числового ID
Здравствуйте, night beast, Вы писали:
NB>Здравствуйте, A13x, Вы писали:
A>>Понадобилось нечто сходное com-овскому IID: с более простым требованием, что классу сопоставляется некоторое уникальное число в пределах compilation unit.
NB>std::type_info/std::type_index
вроде type_index не обязательно по стандарту int или long — https://en.cppreference.com/w/cpp/types/type_index особенно учитывая, что в с++20 удалили operator!= — хоть и добавили 3-way comparison. Хотя разумно предположить, что на всех мыслимых компиляторах с поддержкой rtti он таким и является. Спасибо, посмотрю плотнее.
NB>ну а так можно свое навелосипедить: NB>
Здравствуйте, A13x, Вы писали:
NB>>адрес &TypeInfoImpl<Test>::id можно использовать как шаблонный параметр и если не делать динамические либы, то он должен быть один.
A>если я ничего не упустил, похоже, что в принципе то же самое, что и мой второй вариант,
второй это какой?
A>хотя здесь "TypeInfo" не является целым типом.
не является и нет необходимости указывать это значение для каждого типа. в качестве значения использовать адрес ид.
compile time counter вроде бы хак, ну и в разных единицах трансляции значения для одного типа разными могут быть.
Здравствуйте, A13x, Вы писали:
A>Понадобилось нечто сходное com-овскому IID: с более простым требованием, что классу сопоставляется некоторое уникальное число в пределах compilation unit. A>Нужно для gcc, c++17.
Так сойдёт?
#include <cstddef>
#include <iostream>
template<class T>ptrdiff_t class_id();
static const ptrdiff_t class_id_0=(ptrdiff_t)class_id<void>;
template<class T>ptrdiff_t class_id() {
return (ptrdiff_t)(class_id<T>)-class_id_0;
}
class A {};
class B {};
int main(int argc, char const *argv[]) {
std::cout<<"A="<<class_id<A>()<<"\n";
std::cout<<"B="<<class_id<B>()<<"\n";
std::cout<<"void="<<class_id<void>()<<"\n";
std::cout<<"char*="<<class_id<char*>()<<"\n";
std::cout<<"const char*="<<class_id<const char*>()<<"\n";
std::cout<<"char const*="<<class_id<char const*>()<<"\n";
std::cout<<"char *const="<<class_id<char *const>()<<"\n";
return 0;
}
Здравствуйте, kov_serg, Вы писали:
_>Здравствуйте, A13x, Вы писали:
A>>Понадобилось нечто сходное com-овскому IID: с более простым требованием, что классу сопоставляется некоторое уникальное число в пределах compilation unit. A>>Нужно для gcc, c++17. _>Так сойдёт? _>
Здравствуйте, TailWind, Вы писали:
A>>нет, скорее для безопасных кастов, ближайший аналог — это CComQIPtr или ATL-овская обертка над QueryInterface.
TW>Что-то ты недоброе затеял TW>Почему не стандартный dynamic_cast? TW>И указатель на базовый класс вместо *void
Ну, не будем нарушать традиции русскоязычных форумов и в ответ на вопрос объясним топикстартеру, как он не прав!
Недоброе однозначно: все эти игры с uuidof обычно нужны для создания мощной распределённой расширяемой инфраструктуры. Собственно, такой как COM. Где плагины грузились через браузер, а у сисадмина был гуишный тул (OLEViewer) для контроля кишков. Но у такой инфраструктуры и uuidof'ность стандартизированная (QI с типовым switch внутри, либо, собственно, uuidof за счёт MS specific имплементации метаданных). Городить свою такую… в рамках одного приложения… Скорее всего, лучше просто метаданные сделать данными.
А когда я смотрю, как метаданные делают на шаблонах, кровью плакаю.