Je ne suis pas sûr que ce soit possible du tout ce que j'essaie d'atteindre ces 3 dernières heures sans aucune approche sensorielle.Définition d'un type de gabarit variadique avec une liste d'arguments inconnue comme type de valeur std :: map
J'ai un modèle variadique comme ceci:
template<typename... Ts>
class xunit_test_item {
public:
template<typename F, typename... Args>
xunit_test_item(const std::string& name, F&& func, Args&&... args)
: m_name(name)
, m_f(std::forward<F>(func))
, m_args(std::forward<Args>(args)...)
{
}
// ...
private:
const std::string m_name;
std::function<void (Ts...) > m_f;
std::tuple<Ts...> m_args;
};
enveloppements Au-dessus de modèle un élément de test qui est essentiellement un titulaire d'un foncteur avec des arguments passés le long d'une chaîne pour nommer cet élément.
Les objets de ce type doivent être stockés dans un fichier std :: map comme type de valeur. Ceci est géré dans une classe qui contient un conteneur std::map
en tant que membre, une méthode d'enregistrement pour ajouter des éléments xunit_test_item et une méthode d'exécution, qui itère sur la carte et exécute toutes les fonctions stockées xunit_test_item stockées.
La classe ressemble fondamentalement ceci:
class unit_test {
// Define a map type of xunit_test_items
template<typename ...Ts>
using testitem_map_t = std::map<size_t, xunit_test_item<Ts...>>;
public:
unit_test() = delete;
unit_test(const std::string& group_name)
: m_tm()
, m_group_name(group_name)
, m_test_id(0)
{
}
// Register an functor item
template<typename F, typename ...Args>
void add_test(const std::string& name, F&& fun, Args&& ...args) {
m_tm.emplace(++m_test_id, xunit_test_item<Args...>(
name, std::forward<F>(fun), std::forward<Args>(args)...));
}
void run()
{
// ...
for (auto& t : m_tm) {
// ...
t.second->run();
// ...
}
}
private:
testitem_map_t m_tm; // <-- Compiler correctly reports an error
std::string m_group_name;
size_t m_test_id;
};
Le problème que j'ai est de trouver la bonne approche de syntaxe/différente pour définir le xunit_test_item
comme le type de valeur de l'élément de carte m_tm
. Le code ci-dessus ne compile pas - sans aucun doute - car je dois spécifier une liste d'arguments pour le membre m_tm
avec son type testitem_map_t. Je n'ai aucune idée comment définir ce type et déclarer correctement le membre m_tm
. La liste des arguments est inconnue à ce stade. Peut-être mes classes ci-dessus ont un problème de conception, je me demande s'il existe un moyen plus ou moins simple pour y parvenir. Je peux également complètement ne pas voir une solution simple.
Serait heureux d'apprendre et obtenir une bonne suggestion. Merci d'avance!
Mise à jour
fraîches par jour, frais et essayer une tasse de café ...
Je refactorisé tout le corps de la méthode add_test
utilisant un lambda à 2 niveaux et qui semble fonctionner jusqu'à présent. En tant que fonctions de test (les cas de test réels), je peux ajouter des lambdas, des pointeurs de fonction avec des arguments arbitraires ou non.
Je ne sais pas si c'est la meilleure solution, ou si elle peut être mieux codée, peut-être que quelqu'un veut commenter sur ce sujet. Aussi la raison pour laquelle je n'entre pas cela comme réponse. Mon espoir avec ma question initiale était d'apprendre peut-être du sucre C++ 14 comme solution ... si possible.
Ceci est une première version testée à peu près ...
template<typename F, typename ...Args>
void add_test(const std::string& name, F&& fun, Args&& ...args) {
std::function<void(Args...)> fun_xargs =
[name, fun](auto&&... args) {
std::cout << " inner lambda\n";
auto x = xunit_test_item<Args...>(name, fun, std::forward<Args>(args)...);
x.run();
};
std::function<void()> fun_void =
[=] {
std::cout << "outer lambda\n";
fun_xargs(args...);
};
m_tm.emplace(++m_test_id, fun_void);
}
wrap 'run' dans un lambda et le stocker comme' std :: fonction 'sur la carte –
vu1p3n0x
Note: le paramètre' Args ... 'de' xunit_test_item :: xunit_test_item' ne peut jamais se résoudre en un paquet convertible en 'Ts ...', donc vous pouvez aussi bien utiliser 'Ts .. .' là. – Caleth
@caleth: Bien noté! –