полиморфизм с подклассами другого типа шаблона - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть класс с шаблоном, и некоторые классы наследуются от него.Мы хотим создать экземпляр класса отца, не объявляя его тип шаблона, и вызвать функцию, возвращающую тип шаблона.

Пример:

class FatherWrap {
    virtual ~FatherWrap() = default;
};

template<typename T>
class FatherClass : public FatherWrap
{
    virtual T getValue();
};

class SonClass1 : public FatherClass<int>
{
    int getValue() override;
};

class SonClass2 : public FatherClass<string>
{
    string getValue() override;
};  

int main()
{
    FatherWrap* ch = new SonClass1();
    T a = ch->getValue; // What to do instead of T.
}

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Вы можете полностью пропустить FatherWrap и заставить базовый класс возвращать вариант:

struct FatherClass : FatherWrap {
    virtual std::variant<int, std::string> getValue();
};

struct SonClass1 : FatherClass {
    std::variant<int, std::string> getValue() override {
        return "some text";
    }
};

struct SonClass2 : FatherClass {
    std::variant<int, std::string> getValue() override {
        return 95;
    }
};   

В качестве альтернативы, вы можете создать шаблон любого кода, который использует SonClass:

struct SonClass1 { // no parent.
    std::string getValue() {
        return "some text";
    }
};

struct SonClass2 { // no parent.
    int getValue() {
        return 95;
    }
};

template<typename T>
void useSonClass(T& son) {
    // value may be int or string.
    auto value = son.getValue();
}

int main() {
    SonClass1 sc1;
    SonClass2 sc2;

    useSonClass(sc1);
    useSonClass(sc2);
}

Если вы хотите его содержать, просто используйте вариант:

int main() {
    std::variant<SonClass1, SonClass2> sc = SonClass2{};

    std::visit(
        [](auto& sc) { useSonClass(sc); },
        sc
    );
}
0 голосов
/ 04 февраля 2019

Допустим, у вас есть:

  • Непараметрический (без шаблона) базовый класс B
  • Промежуточный шаблонный класс I<T>, унаследованный от B
  • Некоторые производные классы D1, D2 и т. Д., Каждый из которых наследуется от специализации I

Вы хотите написать некоторый код в терминах B.Вы можете сделать это - но вы должны ограничить себя использованием API, который определяет B.Методы B могут быть виртуальными, и реализации / переопределения этих методов в I<T> и Dx могут использовать тип T, но эти типы не могут быть представлены компоненту, о котором знает только B.

Если вы хотите написать некоторую логику, которая использует T, тогда эта логика должна быть либо в методе I<T>, либо в функции шаблона, которая сама параметризована с типом класса:

template<class U>
U someTypeSpecificLogic(I<U> intermediate) {
    // can call methods that accept/return U here
}

Нельзя писать логику в терминах B, который зависит от типа T, поскольку этот тип определен только для подкласса I<T>.Учтите, что B у вас есть другой подкласс B, а не I<T> вообще.

...