La méthode standard consiste à faire option1
y option2
des classes dérivées d'un base_class
ce qui semble cohérent avec votre échantillon main()
. Utilisation d'un générique Factory
Voici un exemple de modèle de classe :
#include <functional>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <vector>
// Generic Factory class template
template<typename K,typename T,typename... Ts>
class Factory
{
using Map = std::unordered_map<K, std::function<std::unique_ptr<T>(Ts...)>>;
const Map mMap;
public:
Factory(Map&& map):mMap(std::move(map)) { }
std::unique_ptr<T> operator()(const K& key, Ts... args) const
{
const typename Map::const_iterator itr = mMap.find(key);
return itr == mMap.cend() ? nullptr : itr->second(std::forward<Ts>(args)...);
}
};
class base_class
{
public:
virtual void create_data() = 0;
};
class option1 : public base_class
{
public:
void create_data() override
{
std::cout << "I'm option1." << std::endl;
}
};
class option2 : public base_class
{
public:
void create_data() override
{
std::cout << "I'm option2." << std::endl;
}
};
class storage_class
{
using SimulationFactory = Factory<int,base_class>; // Optionally add constructor parameter types
const SimulationFactory simulation_factory; // This can be made static const.
public:
storage_class(int sel, int n)
: simulation_factory(
{ { 1, []() { return std::make_unique<option1>(); } }
, { 2, []() { return std::make_unique<option2>(); } }
})
{
for (int i = 0; i < n; i++)
my_store.push_back(simulation_factory(sel));
}
std::vector<std::unique_ptr<base_class>> my_store;
};
int main()
{
int n_iterations = 4;
storage_class store(1, n_iterations);
for(int i = 0; i < n_iterations; i++)
{
store.my_store[i]->create_data();
}
}
Cela a été compilé pour moi sous linux en utilisant g++ -std=c++17 main.cc
.
Il y a des améliorations qui peuvent être faites à ce code, mais j'ai copié votre main()
afin d'illustrer la ou les idées de base. J'espère que cela vous aidera.
Edit 21 Sept 2018 - Exemple de passage de paramètres dans les constructeurs.
Fichier : factory.h
#pragma once
#include <functional>
#include <memory>
#include <unordered_map>
// Generic Factory class template
template<typename K,typename T,typename... Ts>
class Factory
{
using Map = std::unordered_map<K, std::function<std::unique_ptr<T>(Ts...)>>;
const Map mMap;
public:
Factory(Map&& map):mMap(std::move(map)) { }
std::unique_ptr<T> operator()(const K& key, Ts... args) const
{
const typename Map::const_iterator itr = mMap.find(key);
return itr == mMap.cend() ? nullptr : itr->second(std::forward<Ts>(args)...);
}
};
Fichier : main.cc
#include "factory.h"
#include <iostream>
#include <string>
#include <vector>
class base_class
{
public:
virtual void create_data() = 0;
};
class option1 : public base_class
{
const double mD;
public:
option1(double d)
: mD(d)
{ }
void create_data() override
{
std::cout << "I'm option1: mD("<<mD<<')' << std::endl;
}
};
class option2 : public base_class
{
const double mD;
public:
option2(double d)
: mD(d)
{ }
void create_data() override
{
std::cout << "I'm option2: mD("<<mD<<')' << std::endl;
}
};
class storage_class
{
using SimulationFactory = Factory<int,base_class,double>; // Optionally add constructor parameter types
const SimulationFactory simulation_factory; // This can be made static const.
public:
storage_class(int sel, int n)
: simulation_factory(
{ { 1, [](double d) { return std::make_unique<option1>(d); } }
, { 2, [](double d) { return std::make_unique<option2>(d); } }
})
{
for (int i = 0; i < n; i++)
my_store.push_back(simulation_factory(sel,static_cast<double>(i)));
}
std::vector<std::unique_ptr<base_class>> my_store;
};
int main()
{
int n_iterations = 4;
storage_class store1(1, n_iterations);
storage_class store2(2, n_iterations);
for(int i = 0; i < n_iterations; i++)
{
store1.my_store[i]->create_data();
store2.my_store[i]->create_data();
}
}
Sortie :
I'm option1: mD(0)
I'm option2: mD(0)
I'm option1: mD(1)
I'm option2: mD(1)
I'm option1: mD(2)
I'm option2: mD(2)
I'm option1: mD(3)
I'm option2: mD(3)