Question

J'ai un programme qui génère des graphiques en utilisant différents modèles à plusieurs niveaux. Chaque modèle multi-niveaux est constitué d'une génération d'un plus petit graphique des semences (par exemple, 50 noeuds) qui peut être créé à partir de plusieurs modèles (par exemple - pour chaque bord possible, choisir de l'inclure, avec une probabilité p).

Après la génération du graphe de la graine, le graphique est élargi en un plus grand (disons 1000 noeuds), en utilisant une d'une autre série de modèles.

Dans chacun des deux étages, chaque modèle nécessite un certain nombre de paramètres différents.

Je voudrais être avoir program_options parse les différents paramètres possibles, selon les noms des modèles.

Par exemple, dire que j'ai deux modèles graphiques de semences: SA, qui a 1 paramètres et SB, qui a deux. Aussi pour la partie d'extension, j'ai deux modèles: A et B, de nouveau avec les paramètres 1 et 2, respectivement. Je voudrais être quelque chose capable do comme:

./graph_generator --seed=SA 0.1 --expansion=A 0.2
./graph_generator --seed=SB 0.1 3 --expansion=A 0.2
./graph_generator --seed=SA 0.1 --expansion=B 10 20
./graph_generator --seed=SB 0.1 3 --expansion=B 10 20

et ont les paramètres analysés correctement. Est-ce même possible?

Était-ce utile?

La solution

En utilisant un validateur sur mesure et boost :: program_options: : value :: Multitoken , vous pouvez obtenir le résultat souhaité:

#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <boost/program_options.hpp>

// Holds parameters for seed/expansion model
struct Model
{
    std::string type;
    boost::optional<float> param1;
    boost::optional<float> param2;
};

// Called by program_options to parse a set of Model arguments
void validate(boost::any& v, const std::vector<std::string>& values,
              Model*, int)
{
    Model model;
    // Extract tokens from values string vector and populate Model struct.
    if (values.size() == 0)
    {
        throw boost::program_options::validation_error(
            "Invalid model specification");
    }
    model.type = values.at(0); // Should validate for A/B
    if (values.size() >= 2)
        model.param1 = boost::lexical_cast<float>(values.at(1));
    if (values.size() >= 3)
        model.param2 = boost::lexical_cast<float>(values.at(2));

    v = model;
}

int main(int argc, char* argv[])
{
    Model seedModel, expansionModel;

    namespace po = boost::program_options;
    po::options_description options("Generic options");
    options.add_options()
        ("seed",
             po::value<Model>(&seedModel)->multitoken(),
             "seed graph model")
        ("expansion",
             po::value<Model>(&expansionModel)->multitoken(),
             "expansion model")
        ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, options), vm);
    po::notify(vm);

    std::cout << "Seed type: " << seedModel.type << "\n";
    if (seedModel.param1)
        std::cout << "Seed param1: " << *(seedModel.param1) << "\n";
    if (seedModel.param2)
        std::cout << "Seed param2: " << *(seedModel.param2) << "\n";

    std::cout << "Expansion type: " << expansionModel.type << "\n";
    if (expansionModel.param1)
        std::cout << "Expansion param1: " << *(expansionModel.param1) << "\n";
    if (expansionModel.param2)
        std::cout << "Expansion param2: " << *(expansionModel.param2) << "\n";

    return 0;
}

La fonction validate a probablement besoin d'une plus grande rigueur, mais vous voyez l'idée.

Cette compile et fonctionne pour moi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top