Logs
Consultez les logs.
OK
Liste des données
Consultez la liste des données.
OK
Loading...
Formulaire
Saisissez vos données.
Enregistrer
Annuler

Références Boost

Vues
274

Vous souhaitez bénéficier des fonctionnalités très avancées offertes par une collection de bibliothèques logicielles C++ telles que Boost avec une couverture Multiplateforme (Windows, Linux, Mac)



Installation de Boost


Vous souhaitez installer Boost dans votre environnement de développement. 


Installation sous Windows


On accède à la page officielle de Boost.

https://www.boost.org/

On accède au code source de Boost.

image.png

On télécharge le code source de Boost pour CMake.

image.png

Ouvre le Terminal du compilateur MSVC.

image.png

On démarre la construction et l'installation de Boost.

...
bootstrap.bat
b2
b2 install
...

On accède au répertoire d'installation de boost.

C:
|-- Boost
|   |-- include
|   |   |-- boost-1_88
|   |
|   |-- lib
|   |    |-- cmake


Configuration de CMake


Vous pouvez utiliser l'outil CMake pour construire vos projets C++ à base de la librairie Boost. 


Fichier CMake racine (CMakeLists.txt)


On définit le nom du projet. 

...
cmake_minimum_required(VERSION 3.10.0)
project(ReadyBOOST VERSION 0.1.0 LANGUAGES C CXX)
...

On active les standards C++11. 

...
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)
...

On active la nouvelle politique CMake pour supprimer les warnings avec Boost. 

...
if(POLICY CMP0167)
    cmake_policy(SET CMP0167 NEW)
endif()
...

On fixe le type de construction CMake à la valeur (Debug) s'il n'est pas défini dans un environnement (MSVC). 

...
if (NOT CMAKE_BUILD_TYPE)
    if(MSVC)
        set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build type" FORCE)
    endif()
endif()

message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
...

On indique le chemin du répertoire des fichiers CMake de Boost. 

...
list(APPEND CMAKE_PREFIX_PATH "C:/Boost/lib/cmake")
...

On recherche les composants du package Boost à utiliser. 

...
find_package(Boost REQUIRED COMPONENTS
    program_options
)
...

On indique le répertoire des fichiers sources. 

...
add_subdirectory(src)
...

Fichier CMake source (src/CMakeLists.txt)


On indique le répertoire des fichiers projets. 

...
add_subdirectory(program_options_base)
add_subdirectory(program_options_short)
...

Fichier CMake projet (src/project/CMakeLists.txt)


On définit le nom du projet. 

...
project(program_options_base)
...

On définit les sources du projet. 

...
set(SRC_FILES
    main.cpp
)
...

On ajoute des fichiers ressource dans le répertoire de construction CMake du fichier exécutable. 

...
set(RES_FILES
    res/config/options.cfg
)

if (NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
    set(RES_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}")
    message(STATUS "RES_DIR : " ${RES_DIR})
    foreach(RES_FILE IN LISTS RES_FILES)
        message(STATUS "RES_FILE : " ${RES_FILE})
        add_custom_command(
            OUTPUT "${RES_DIR}/${RES_FILE}"
            COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/${RES_FILE}" "${RES_DIR}/${RES_FILE}"
            DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${RES_FILE}"
        )
    endforeach()
endif()
add_custom_target(data_${PROJECT_NAME} ALL DEPENDS ${RES_FILES})
...

On crée le fichier exécutable. 

...
add_executable(${PROJECT_NAME}
    ${SRC_FILES}
)
...

On édite les liens du fichier exécutable avec les librairies Boost. 

...
target_link_libraries(${PROJECT_NAME}
    ${Boost_LIBRARIES}
)
...


Configuration de VSCode


Vous pouvez utiliser l'éditeur VSCode pour développer vos projet C++ à base de la librairie Boost et l'outil CMake. 


Fichier de configuration (settings.json)


On initialise le fichier de configuration. 

...
{
    ...
}
...

On définit les arguments à passer en ligne de commande au fichier exécutable généré par CMake.

...
{
    ...
    "cmake.debugConfig": {
        "args": [
            "--apples=10",
            "--oranges=20"
        ]
    }
    ...
}
...


Configuration des lanceurs Batch sous Windows


Vous pouvez utiliser les scripts Batch sous Windows pour faciliter le lancement de vos exécutables construits à partir de la librairie Boost. 


Fichier Batch (cmd-config.bat)


On interdit d'afficher le contenu du script. 

...
@echo off
...

On initialise les paramètres du script. 

...
@echo off
set "root_dir=..\..\.."
set "program_name=program_options_base"
set "config_mode=Debug"
set "build_dir=%root_dir%\build"
set "program_dir=%root_dir%\build\src\%program_name%\%config_mode%"
set "setup=%program_name%.exe"
set cmake_exe="C:\Program Files\CMake\bin\cmake.exe"
...

Fichier Batch (cmd-run-help.bat)


On lance le programme avec l'option (help). 

...
@echo off
call cmd-config.bat
pushd %program_dir%
%setup% --help
popd
...

Fichier Batch (cmd-run.bat)


On lance le programme sans aucune option. 

...
@echo off
call cmd-config.bat
pushd %program_dir%
%setup%
popd
...

Fichier Batch (cmd-run-options-define.bat)


On lance le programme avec toutes les options. 

...
@echo off
call cmd-config.bat
pushd %program_dir%
%setup% --oranges 5 --apples 10
popd
...

Fichier Batch (cmd-run-options-help.bat)


On lance le programme avec toutes les options y compris l'option (help).

...
@echo off
call cmd-config.bat
pushd %program_dir%
%setup% --oranges 5 --apples 10 --help
popd
...


Utilisation de Boost Program Options


Vous pouvez utiliser la librairie Boost Program Options pour gérer les options de vos programmes C++. 


Utilisation de base



Programme C++ (main.cpp)


On inclut les fichiers d'entête. 

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

On définit les raccourcis des espaces des noms. 

...
namespace opt = boost::program_options;
...

On crée le module de description des options du programme. 

...
int main(int argc, char **argv)
{
    opt::options_description desc("All options");
    ...
    return 0 ;
}
...

On définit les options du programme. 

...
int main(int argc, char **argv)
{
    ...
    desc.add_options()
        ("apples", opt::value<int>(), "how many apples do you have")
        ("oranges", opt::value<int>(), "how many oranges do you have")
        ("help", "produce help message");
    ...
}
...

On charge les arguments passés en ligne de commande pour créer un dictionnaire de variables d'options. 

...
int main(int argc, char **argv)
{
    ...
    opt::variables_map vm;
    opt::store(opt::parse_command_line(argc, argv, desc), vm);
    opt::notify(vm);
    ...
}
...

On affiche le menu d'aide si l'option (help) est présente. 

...
int main(int argc, char **argv)
{
    ...
    if (vm.count("help"))
    {
        std::cout << desc << "\n";
        return 1;
    }
    ...
}
...

On calcule le nombre de fruits à partir des valeurs des options (apples et oranges). 

...
int main(int argc, char **argv)
{
    ...
    std::cout << "Fruits count: "
              << vm["apples"].as<int>() + vm["oranges"].as<int>()
              << std::endl;
    ...
}
...

Résultat des Tests


On lance le programme avec l'option (help). 

...
setup.exe --help
...
All options:
  --apples arg          how many apples do you have
  --oranges arg         how many oranges do you have
  --help                produce help message
...

On lance le programme avec les options (oranges et apples). 

...
setup.exe --oranges 5 --apples 10
...
...
Fruits count: 15
...

On lance le programme avec l'option (oranges, apples et help).

...
setup.exe --oranges 5 --apples 10 --help
...
All options:
  --apples arg          how many apples do you have
  --oranges arg         how many oranges do you have
  --help                produce help message
...

Utilisation des options courtes



Programme C++ (main.cpp)


On inclut les fichiers d'entête.

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

On définit les raccourcis des espaces des noms.

...
namespace opt = boost::program_options;
...

On crée le module de description des options du programme.

...
int main(int argc, char **argv)
{
    opt::options_description desc("All options");
    ...
    return 0 ;
}
...

On définit les options du programme. On attribut des noms courts aux options (oranges et apples). On rend l'option (oranges) obligatoire. On définit une valeur par défaut pour l'option (apples). Les autres options (help et name) sont facultatives.

...
int main(int argc, char **argv)
{
    ...
    int oranges_var = 0;
    desc.add_options()
        ("oranges,o", opt::value<int>(&oranges_var)->required(), "oranges that you have")
        ("name", opt::value<std::string>(), "your name")
        ("apples,a", opt::value<int>()->default_value(10), "apples that you have")
        ("help", "produce help message");
    ...
}
...

On charge les arguments passés en ligne de commande pour créer un dictionnaire de variables d'options. 

...
int main(int argc, char **argv)
{
    ...
    opt::variables_map vm;
    opt::store(opt::parse_command_line(argc, argv, desc), vm);
    ...
}
...

On affiche le menu d'aide si l'option (help) est présente. 

...
int main(int argc, char **argv)
{
    ...
    if (vm.count("help"))
    {
        std::cout << desc << "\n";
        return 1;
    }
    ...
}
...

On charge le fichier de configuration pour initialiser les valeurs des options prédéfinies dans le fichier et non fournies en ligne de commande. 

...
int main(int argc, char **argv)
{
    ...
    const char *configFile = "res/config/options.cfg";

    try
    {
        opt::store(opt::parse_config_file<char>(configFile, desc), vm);
    }
    catch (const opt::reading_file &e)
    {
        std::cout << "Error: " << e.what() << std::endl;
    }
    ...
}
...

On notifie la mise à jour de la logique interne du gestionnaire d'options. 

...
int main(int argc, char **argv)
{
    ...
    try
    {
        opt::notify(vm);
    }
    catch (const opt::required_option &e)
    {
        std::cout << "Error: " << e.what() << std::endl;
        return 2;
    }
    ...
}
...

On affiche le nom si l'option (name) est présente.

...
int main(int argc, char **argv)
{
    ...
    if (vm.count("name"))
    {
        std::cout << "Hi," << vm["name"].as<std::string>() << "!\n";
    }
    ...
}
...

On calcule le nombre de fruits à partir des valeurs des options (apples et oranges). 

...
int main(int argc, char **argv)
{
    ...
    std::cout << "Fruits count: "
              << vm["apples"].as<int>() + vm["oranges"].as<int>()
              << std::endl;
    ...
}
...

Fichier de configuration (options.cfg)


On initialise les options (oranges et name) à partir du fichier de configuration. 

...
# Fichier de configuration des options
oranges=20
name=ReadyDEV
...

Résultat des Tests


On lance le programme avec l'option (help). 

...
setup.exe --help
...
All options:
  -o [ --oranges ] arg      oranges that you have
  --name arg                your name
  -a [ --apples ] arg (=10) apples that you have
  --help                    produce help message
...

On lance le programme sans aucune option. 

...
setup.exe
...
Hi,ReadyDEV!
Fruits count: 30
...

On lance le programme avec les options (oranges, apples et name). 

...
setup.exe --oranges 5 --apples 10 --name ReadyTEAM
...
Hi,ReadyTEAM!
Fruits count: 15
...

On lance le programme avec les options (oranges, apples, name et help). 

...
setup.exe --oranges 5 --apples 10 --name ReadyTEAM --help
...
All options:
  -o [ --oranges ] arg      oranges that you have
  --name arg                your name
  -a [ --apples ] arg (=10) apples that you have
  --help                    produce help message
...


Utilisation de Boost Any


Vous pouvez utiliser le type de donnée (Boost Any) pour stocker n'importe quel type de donnée dans vos projets C++.


Utilisation de base



Programme C++ (main.cpp)


On inclut les fichiers d'entête. 

...
#include <boost/any.hpp>
#include <iostream>
#include <vector>
#include <string>
...

On crée la liste de données de types quelconques. 

...
int main(int argc, char **argv)
{
    std::vector<boost::any> some_values;
    ...
    return 0 ;
}
...

On stocke les données de types quelconques. 

...
int main(int argc, char **argv)
{
    ...
    some_values.push_back(10);
    const char *c_str = "Hello there!";
    some_values.push_back(c_str);
    some_values.push_back(std::string("Wow!"));
    ...
}
...

On récupère la référence sur la dernière donnée de la liste de données.

...
int main(int argc, char **argv)
{
    ...
    std::string &s = boost::any_cast<std::string &>(some_values.back());
    ...
}
...

On modifie et on affiche la dernière donnée pour vérifier le pointeur de référence. 

...
int main(int argc, char **argv)
{
    ...
    s += " That is great!\n";
    std::cout << s;
    std::cout << boost::any_cast<std::string &>(some_values.back());
    ...
}
...

Résultat des Tests


On lance le programme.

...
setup.exe
...
Wow! That is great!
Wow! That is great!
...
Le pointeur de référence fonctionne correctement.
...

Utilisation d'une base de données



Programme C++ (main.cpp)


On inclut les fichiers d'entête.

...
#include <boost/any.hpp>
#include <vector>
#include <string>
#include <typeinfo>
#include <algorithm>
#include <functional>
#include <iostream>
...

On crée les raccourcis de types. 

...
using cell_t = boost::any;
using db_row_t = std::vector<cell_t>;
...

On crée la fonction de lecture d'une ligne de données. 

...
db_row_t get_row(const char *query)
{
    std::cout << "Executing query: " << query << std::endl;
    db_row_t row;
    row.push_back(10);
    row.push_back(10.1f);
    row.push_back(std::string("hello again"));
    return row;
}
...

On crée le foncteur pour réaliser la somme des données numériques. 

...
struct db_sum : public std::function<void(cell_t)>
{
private:
    double &sum_;

public:
    explicit db_sum(double &sum)
        : sum_(sum)
    {
    }

    void operator()(const cell_t &value)
    {
        const std::type_info &ti = value.type();
        if (ti == typeid(int))
        {
            sum_ += boost::any_cast<int>(value);
        }
        else if (ti == typeid(float))
        {
            sum_ += boost::any_cast<float>(value);
        }
    }
};
...

On récupère la ligne de données. 

...
int main(int argc, char **argv)
{
    db_row_t row = get_row("Query: Give me some row, please.");
    ...
    return 0 ;
}
...

On réalise la somme des données numériques. 

...
int main(int argc, char **argv)
{
    ...
    double res = 0.0;
    std::for_each(row.begin(), row.end(), db_sum(res));
    std::cout << "Sum of arithmetic types in database row is: " << res << std::endl;
    ...
}
...

Résultat des Tests


On lance le programme. 

...
setup.exe
...
Executing query: Query: Give me some row, please.
Sum of arithmetic types in database row is: 20.1
...


Utilisation de Boost Variant


Vous pouvez utiliser le type de donnée (Boost Variant) pour stocker n'importe quel type de donnée à partir d'une liste de types de données prédéfinis dans vos projets C++.


Utilisation de base



Programme C++ (main.cpp)


On inclut les fichiers d'entête. 

...
#include <boost/variant.hpp>
#include <vector>
#include <string>
#include <iostream>
...

On crée le type liste de types de données quelconques. 

...
int main(int argc, char **argv)
{
    typedef boost::variant<int, const char *, std::string> my_var_t;
    ...
    return 0 ;
}
...

On crée la liste de données de types quelconques. 

...
int main(int argc, char **argv)
{
    ...
    std::vector<my_var_t> some_values;
    ...
}
...

On stocke les données de types quelconques parmi la liste de types. 

...
int main(int argc, char **argv)
{
    ...
    some_values.push_back(10);
    some_values.push_back("Hello there!");
    some_values.push_back(std::string("Wow!"));
    ...
}
...

On récupère la référence sur la dernière donnée de la liste de données. 

...
int main(int argc, char **argv)
{
    ...
    s += " That is great!\n";
    std::cout << s;
    std::cout << boost::get<std::string>(some_values.back());
    ...
}
...

Résultat des Tests


On lance le programme.

...
setup.exe
...
Wow! That is great!
Wow! That is great!
...
Le pointeur de référence fonctionne correctement.
...

Utilisation d'une base de données



Programme C++ (main.cpp)


On inclut les fichiers d'entête. 

...
#include <boost/variant.hpp>
#include <iostream>
#include <vector>
#include <string>
...

On crée les raccourcis de types. 

...
using cell_t = boost::variant<int, float, std::string>;
using db_row_t = std::vector<cell_t>;
...

On crée la fonction de lecture d'une ligne de données. 

...
db_row_t get_row(const char *query)
{
    std::cout << "Executing query: " << query << std::endl;
    db_row_t row;
    row.push_back(10);
    row.push_back(10.1f);
    row.push_back("hello again");
    return row;
}
...

On crée le foncteur pour réaliser la somme des données numériques. 

...
struct db_sum_visitor : public boost::static_visitor<double>
{
    double operator()(int value) const
    {
        return value;
    }
    double operator()(float value) const
    {
        return value;
    }
    double operator()(const std::string &value) const
    {
        return 0.0;
    }
};
...

On récupère la ligne de données. 

...
int main(int argc, char **argv)
{
    db_row_t row = get_row("Query: Give me some row, please.");
    ...
    return 0 ;
}
...

On réalise la somme des données numériques. 

...
int main(int argc, char **argv)
{
    ...
    double res = 0.0;
    for (db_row_t::const_iterator it = row.begin(), end = row.end(); it != end; ++it)
    {
        res += boost::apply_visitor(db_sum_visitor(), *it);
    }
    std::cout << "Sum of arithmetic types in database row is: " << res << std::endl;
    ...
}
...

Résultat des Tests


On lance le programme.

...
setup.exe
...
Executing query: Query: Give me some row, please.
Sum of arithmetic types in database row is: 20.1
...