LINUX.ORG.RU

Возможна ли в C++ compile-time интроспекция?

 , интроспекция


0

2

Суть такова: со стороны передается некий объект. Могу ли я определить его тип и получить доступ к его структуре до исполнения программы? В нынешних стандартах что-то предусмотрено для этого? Может быть, сторонние библиотеки?

Всем спасибо.

если речь про рефлексию то ее пока нет в плюсах, надо пользоваться библиотеками вроде boost hana. Что есть - можно например выбирать перегрузки в зависимости, есть ли у класса какое-то поле.

void foo(auto a) requires requires { a.bar; } {
    std::cout << "has bar field\n";
}

void foo(auto a) {
    std::cout << "no bar field\n";
}
Lrrr ★★★★★
()
Ответ на: комментарий от ox55ff

Ну скажем, мне передается экземпляр типа Object (что за тип - неизвестно, просто передался), надо определить в compile time, что же это за тип, какие у него методы, ну и иметь возможность их дергать. Короче как в java.reflection.

LongLiveUbuntu ★★★★★
() автор топика
Ответ на: комментарий от LongLiveUbuntu

что же это за тип, какие у него методы, ну и иметь возможность их дергать

Если ты собираешься вызывать методы, то наверное знаешь какие именно, а значит достаточно просто отнаследоваться от интерфейса и проверять реализует ли его класс? Если бы ты описал задачу более подробно, то возможно тебе бы ответили как это сделать без рефлексии.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от LongLiveUbuntu

Если известна сигнатура метода, наличие которого нужно проверить в переданном типе, то это можно сделать через шаблоны. А если есть c++20, то можно через концепты. Просто так получить список методов не выйдет.

ox55ff ★★★★★
()
Ответ на: комментарий от LongLiveUbuntu

Можно но криво. И для каждого такого типа придётся руками инициировать сбор метаинформации. Да и со списками в компайл-тайм работать такое себе…

КМК у Вас постановка странная. Оно точно надо? Если да то зачем, можно сценарий использования? В рантайм это выглядит нормально, а вот в компайл-тайм…

AntonI ★★★★★
()
Ответ на: комментарий от LongLiveUbuntu

Ну скажем, мне передается экземпляр типа Object (что за тип - неизвестно, просто передался), надо определить в compile time, что же это за тип, какие у него методы, ну и иметь возможность их дергать

Если объект передаётся в run time, то в compile time о нём ещё неизвестно. Максимум, что можно сделать - некую диспетчеризацию: вычитать откуда-то признак типа и, в случае успешного распознавания, скастовать объект к заранее объявленному конкретному типу с методами и т.д.

annulen ★★★★★
()

Все плюсовики когда-то через это желание проходят. Кратко: нет. Варианты:

  1. Описывать структуры на другом языке, генерировать по ним плюсовый код (аки protobuf и компания);
  2. Описывать структуры хитрыми макросами, которые используют «лямбда-макрос» внутри. Это путь boost::hana и подобных;
  3. Страдать, писать кучу boilerplate руками или макросами vim. Создаёт видимость бурной деятельности и много строчек однотипного кода;
  4. Молиться, когда стандартизируют reflection, его нормально реализуют компиляторы, и новый стандарт разрешат использовать в проекте;
  5. Написать плагин для gcc/clang, как это сделали в https://www.codesynthesis.com/products/odb/
  6. Не использовать C++ там, где такая необходимость возникает. Написать биндинги к какому-нибудь питону, и заниматься интроспекцией уже там.
snizovtsev ★★★★★
()
Последнее исправление: snizovtsev (всего исправлений: 1)
Ответ на: комментарий от snizovtsev

до исполнения программы?

Написать биндинги к какому-нибудь питону, и заниматься интроспекцией уже там.

UPD. Блин, @MOPKOBKA опередил. :)

dimgel ★★★★★
()
Последнее исправление: dimgel (всего исправлений: 1)

Тебе наверно нужна связка if constexpr и requires из C++23.

template<class T> 
void fill(T& container, std::size_t size) { 
    if constexpr (requires {container.reserve(size); }) { 
        container.reserve(size); 
    }

    for (std::size_t i = 0; i < size; i++) {
        container.push_back(i);
    }
}

пример

dvetutnev
()
4 июля 2023 г.
Ответ на: комментарий от LongLiveUbuntu

по сути эта задача даже не сопоставима с constexpr new() — поскольку, что бы компилятору сделать предположения о том, какой тип на самом деле имеет эта сущность — надо сперва ее получить в реальности в исполняемом коде — а она может прийти извне или из другого юнита трансляции...

другими словами — построить статический вариант кода на основе различия поставляемого «неизвестного» типа сущности невозможно — можно лишь создать ветви обработки для рантайма.

safocl ★★
()
Последнее исправление: safocl (всего исправлений: 1)