Использование Type-Erasure для создания запросов type_traits во время выполнения

Можно ли вообще использовать Type Erasure для создания объектов, которые инкапсулируют произвольный тип (назовем его ErasedType), и к которым можно запросить во время выполнения, чтобы определить, можно ли преобразовать другой произвольный тип T в ErasedType?

Подумав об этом, я не думаю, что это возможно, хотя кажется, что это могло потенциально возможно в теории. Компилятор будет знать, какие типы T мы пытаемся сравнить с ErasedType, и поэтому сможет сгенерировать необходимый код перед выполнением. Проблема в том, что на практике не существует ЛЮБОГО способа передать тип параметра шаблона из экземпляра базового класса в экземпляр подкласса.

Например:

struct FooBase
{
    template <class TestType>
    bool is_convertible()
    {
        return call_derived();
    }

    protected:

    virtual bool call_derived() = 0;

    template <class ErasedType>
    void base_class_function() { }
};

template <class ErasedType>
struct Foo : public FooBase
{
    bool call_derived()
    {
        // Here we have access to the ErasedType but no access to TestType.
            //
        // We could pass ErasedType to a base class function by saying:
        //
        // this->base_class_function<ErasedType>();
        //
        // ...but that doesn't seem to help since we still don't have access to
        // TestType
    }
};



Итак, цель состоит в том, чтобы иметь возможность сказать что-то вроде:

FooBase* f = new Foo<int>();
bool res1 = f->is_convertible<double>(); // returns true
bool res2 = f->is_convertible<long>(); // returns true
bool res3 = f->is_convertible<std::string>(); // returns false

Но я не понимаю, как можно реализовать метод FooBase::is_convertible, поскольку я не вижу способа сделать TestType и ErasedType доступными вместе в одной функции, чтобы компилятор мог вычислить результат std::is_convertible<TestType, ErasedType>::value.

Так это вообще возможно?


person Channel72    schedule 10.08.2012    source источник
comment
Вашему базовому классу со стертым типом разрешено предоставлять виртуальную функцию, которая дает вам type_id конкретного типа... но черты - это конструкция времени компиляции, которая на самом деле не взаимодействует с динамической типизацией.   -  person Kerrek SB    schedule 10.08.2012
comment
@KerrekSB: ... хотя вы можете создать структуру поиска во время выполнения с этой информацией ... и запрашивать ее во время выполнения. Другой альтернативой может быть имитация двойной отправки при стирании типа для прохождения «конвертируемой» проверки... любой из них требует довольно много шаблонного кода и не будет полностью универсальным.   -  person David Rodríguez - dribeas    schedule 10.08.2012
comment
@ Дэвид, даже при двойной отправке вы все равно теряете параметр шаблона всякий раз, когда вызываете полиморфную функцию, так как же вы можете устроить ситуацию, когда TestType и ErasedType ОБА не скрыты?   -  person Channel72    schedule 10.08.2012
comment
@Channel72: Вот почему я заметил, что вам понадобится большое количество шаблона, отличие от другого подхода в том, что вы можете реализовать тест для типов стирания... При наличии достаточного количества времени вы можете реализовать это с точки зрения списков типов в классе свойств. Неполностью общая часть комментария связана с тем, что он будет выбирать только конверсии, определенные вами в этом списке/поиске.   -  person David Rodríguez - dribeas    schedule 10.08.2012
comment
(Общая) проблема здесь заключается в том, что вам нужен квадратичный объем данных о типах (учитывая, что вы не можете получить доступ к внутреннему, линейному объему данных о них компилятора), но механизм виртуального/шаблона способен генерировать только линейный объем (как можно увидеть, рассмотрев случай, когда каждый аргумент типа определен только в своей собственной единице перевода).   -  person Davis Herring    schedule 28.02.2020


Ответы (1)


Это действительно невозможно в C++, вообще. Для выполнения произвольных запросов о типах во время выполнения требуется довольно много метаданных, и C++ пытается свести это к минимуму (иногда до такой степени, что это немного раздражает; функция может автоматически включаться «при использовании», поэтому лишних накладных расходов нет, но я отвлекся).

Как намекал Дэвид, вполне возможно дублировать информацию компилятора до определенного момента, но никогда полностью автоматически. Это ограничивает информацию о типе среды выполнения тем, что вы добавляете вручную.

Взгляните на такие библиотеки, как Qt, которые имеют целую структуру поверх C++ для предоставьте эти метаданные, чтобы увидеть, какая работа задействована. В зависимости от решаемой проблемы вы можете обойтись без него.

person GManNickG    schedule 10.08.2012