Шаблоны против полиморфизма - PullRequest
0 голосов
/ 06 мая 2019

Я пишу библиотеку для генетических алгоритмов / нейроэволюции.В настоящее время программа использует полиморфизм, чтобы позволить несколько типов геномов.Итак, мой код выглядит следующим образом:

class Genome { // Interface
    // Some abstract functions 
}

class SpecificGenome : public Genome {
    // implementation
public:   
    int do_something(int x); // Specific behavior, which only this SpecificGenome has
}

class Population {
public:
    Population(size_t population_size, std::function<std::unique_ptr<Genome>()> create_genome);
    // Some functions
    std::vector<std::unique_ptr<Genome>> members;
}

std::unique_ptr<Genome> create_specific_genome(){
    return std::unique_ptr<Genome>(std::make_unique<SpecificGenome>());
}

int main() {
    Population p(150, &create_specific_genome);

    int y = static_cast<SpecificGenome>(*p.members[0].get())->do_something(4);
}

Я думаю изменить его так, чтобы он использовал шаблоны вместо полиморфизма, потому что каждый геном кодирует феном, который может иметь любой тип поведения и не имеетделиться чем-нибудь общим с другими типами феномов, и некоторые геномы используют прямую схему кодирования и не должны декодироваться в феном.Таким образом, каждый геном должен быть приведен к соответствующему подклассу пользователем, чтобы показать его поведение, которое выглядит очень некрасиво.Проблема в том, что каждый подкласс Генома является Геномом и должен иметь несколько специфических функций для работы, поэтому полиморфизм будет иметь смысл.

Редактировать: Вопрос в том виде, в каком он сейчас есть, очень неясен, поэтому я хотел добавить дополнительное объяснение.Я хочу иметь возможность создавать население с любым типом генома (NeuralNetwork, NEAT Genome, изображение, ...), поэтому я сделал это, используя интерфейс и подклассы, чтобы вектор в популяции мог хранить каждый тип, используяуказатель генома.Это было полезно, потому что каждый тип генома должен иметь определенные методы, такие как кроссовер и мутация.Проблема возникает, когда я хочу использовать определенные функции, такие как вычисление вывода нейронной сети, декодирование генома или получение пиксельных данных изображения, декодирование генома.Это заставило меня задуматься, будет ли лучше использовать шаблоны вместо наследования.

1 Ответ

2 голосов
/ 06 мая 2019

Шаблон может помочь вашему делу лучше, но имеет другое значение.

Например, ваш список не может быть разнородным, в каком типе генома он содержится. Это должно быть все одного типа. Если вам нужна гетерогенность, вам придется реализовать какое-либо стирание типа.

Вот пример, похожий на ваш, но со статическим полиморфизмом:

// no inheritance
class SpecificGenome {
public:   
    int do_something(int x);
}

template<typename G, typename C>
class Population {
public:
    Population(size_t population_size, C create_genome);

    // no need for pointers. Values work just fine.
    std::vector<G> members;
}

// Deduction guide using the create_genome function return type
template<typename C>
Population(std::size_t, C) -> Population<std::invoke_result_t<C>, C>;

SpecificGenome create_specific_genome() {
    return SpecificGenome{};
}

int main() {
    // Uses class template argument deduction
    Population p(150, create_specific_genome);

    int y = p.members[0].do_something(4);
}

Кстати, если вы по-прежнему используете std::unique_ptr, вы можете использовать его с гораздо лучшим синтаксисом:

std::unique_ptr<Genome> create_specific_genome() {
    // no need for casts
    return std::make_unique<SpecificGenome>();
}

// no need for calls to `get`.
int y = static_cast<SpecificGenome&>(*p.members[0]).do_something(4);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...