Здравствуйте, Went, Вы писали:
W>Усовершенствую библиотеку рефлексии свою я. Для фабрик классов нужно это. W>Класс может быть инстанцируемым по типу, а может и не быть. Может быть клонируем, а может и не быть. Получается 4 разных случая. Хотелось бы чтобы компилер сам выбирал нужное решение, а для тех классов, которые не клонируются или не инстанцируются, делал заглушки, которые бы вызывали исключения.
Беда в том, что, для того чтобы быть DefaultConstructible (не говоря уже о CopyConstructible), должны соблюдаться условия:
— нет чисто виртуальных функций
— есть соответствующая сигнатура конструктора (конструктор копирования есть всегда)
— и эта сигнатура доступна (т.е. public)
Так вот, с последним пунктом гарантированы проблемы. В С++ нет возможности проверять доступность, только видимость. А видимость и доступность пенпердикулярны.
Поэтому даже если ты проверишь наличие (в MSVC это можно делать, используя псевдонимы — кажется, __ctor, __cctor), то ничего этим не докажешь.
Раз ты пишешь рефлексию, то может быть, проще всего было бы прямо в классе декларировать его роли.
class MyClass : REFLECTION(MyClass, reflectDefaultConstructible) { ..... };
и затем статик-ассертом проверять, не задекларировано ли чего лишнего. (Можно по умолчанию декларировать как запрет, так и разрешение — в зависимости от того, что чаще встречается).
Заодно получаешь возможность вручную блокировать ту-или-иную-конструируемость у классов.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Перекуём баги на фичи!
Re: Определение конструируемости объекта заданного типа.
W>Как узнать на этапе компиляции (а-ля boost::type_traits): W>1. Конструируем ли объект по умолчанию? То есть он не абстрактен, у него есть конструктор по умолчанию и он публичный. W>2. Конструируем ли объект копированием? То есть он не абстрактен и его конструктор копии (не опрерато присваивания) публичный. W>В бусте вроде именно такого нет. Хелп плиз
Похоже что никак.
В бусте это вроде есть в type-traits но там говориться что мол требуется
специальная поддержка компилятора. На практике это конечно не работает.
Через SFINAE у меня тоже не получилось. Именно по причине того, что нельзя разрулить public\private.
Лично я остановился на том что ввёл свой type-traits по умолчанию все типы конструируемы,
а если где-то не собираются делаю явную специализацию.
На практике не конструируемых классов, которые надо регистрировать не так и много оказалось.
Как узнать на этапе компиляции (а-ля boost::type_traits):
1. Конструируем ли объект по умолчанию? То есть он не абстрактен, у него есть конструктор по умолчанию и он публичный.
2. Конструируем ли объект копированием? То есть он не абстрактен и его конструктор копии (не опрерато присваивания) публичный.
В бусте вроде именно такого нет. Хелп плиз
Re: Определение конструируемости объекта заданного типа.
Здравствуйте, Went, Вы писали:
W>Как узнать на этапе компиляции (а-ля boost::type_traits): W>1. Конструируем ли объект по умолчанию? То есть он не абстрактен, у него есть конструктор по умолчанию и он публичный. W>2. Конструируем ли объект копированием? То есть он не абстрактен и его конструктор копии (не опрерато присваивания) публичный.
Для каких целей нужно?
Чтобы сделать compile-time assert, достаточно так
int const assertDefaultConstructible = sizeof( new T() );
int const assertCopyConstructible = sizeof( new T(*(T*)malloc(0)) ); // или даже new T(*(T*)NULL), но это может спровоцировать варнинг
А чтобы SFINAE... видимо, никак. Но мне и придумать сложно ситуацию, в которой потребовалось бы в зависимости от конструируемости идти по разным веткам.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Перекуём баги на фичи!
Re[2]: Определение конструируемости объекта заданного типа.
Здравствуйте, Кодт, Вы писали:
К>Для каких целей нужно? К>Чтобы сделать compile-time assert, достаточно так К>
К>int const assertDefaultConstructible = sizeof( new T() );
К>int const assertCopyConstructible = sizeof( new T(*(T*)malloc(0)) ); // или даже new T(*(T*)NULL), но это может спровоцировать варнинг
К>
Нет, compile-time assert не нужен. Нужны разные ветки.
К>А чтобы SFINAE... видимо, никак. Но мне и придумать сложно ситуацию, в которой потребовалось бы в зависимости от конструируемости идти по разным веткам.
Усовершенствую библиотеку рефлексии свою я. Для фабрик классов нужно это.
Класс может быть инстанцируемым по типу, а может и не быть. Может быть клонируем, а может и не быть. Получается 4 разных случая. Хотелось бы чтобы компилер сам выбирал нужное решение, а для тех классов, которые не клонируются или не инстанцируются, делал заглушки, которые бы вызывали исключения.
Re[4]: Определение конструируемости объекта заданного типа.
Здравствуйте, Кодт, Вы писали:
К>Беда в том, что, для того чтобы быть DefaultConstructible (не говоря уже о CopyConstructible), должны соблюдаться условия: К>- нет чисто виртуальных функций К>- есть соответствующая сигнатура конструктора (конструктор копирования есть всегда) К>- и эта сигнатура доступна (т.е. public) К>Так вот, с последним пунктом гарантированы проблемы. В С++ нет возможности проверять доступность, только видимость. А видимость и доступность пенпердикулярны. К>Поэтому даже если ты проверишь наличие (в MSVC это можно делать, используя псевдонимы — кажется, __ctor, __cctor), то ничего этим не докажешь.
Да. Почти к этому же я пришел
К>Раз ты пишешь рефлексию, то может быть, проще всего было бы прямо в классе декларировать его роли. К>
Вот
К>и затем статик-ассертом проверять, не задекларировано ли чего лишнего. (Можно по умолчанию декларировать как запрет, так и разрешение — в зависимости от того, что чаще встречается). К>Заодно получаешь возможность вручную блокировать ту-или-иную-конструируемость у классов.
Боюсь, автоопределение все-таки ценнее
Re[2]: Определение конструируемости объекта заданного типа.