Je suis en train de coder un wrapper pour sqlite afin de simplifier l'utilisation de libsqlite3 qui est un vrai enfer. J'arrive a lancer des requêtes et récupérer des données, mais j'aimerais étendre ce que j'ai fait pour pouvoir appliquer une fonction a chaque ligne de donnée récupérée.
Voila la version simplifiée de mon problème (on suppose que je récupère qu'une ligne de ma table à la fois)
J'ai une fonction get_data qui marche, et qui me permet d'extraire des données et de les ranger dans un tuple. Derrière il y a un peu de magie, pour apperler les bonnes fonction sqlite en fonction du type template, et pour cracher des erreurs si le type reçu n'est pas celui du template.
Cette fonction est pratique, je peux par exemple écrire.
std::tuple<int,std::string> age_pers=get_data<int,std::string>("select age,nom from personne limit 1");
auto age_pers2 = get_data<int,std::string>("select age,nom from personne limit 1");
J'aimerais ensuite écrire du code générique qui applique a la volée (c'est a dire sans tout stocker dans un container) une fonction utilisateur aux données renvoyées par get_data. Ceci pose trois probmèles: - J'écris quoi dans les <> du template pour passer une fonction qui marche avec les fonctions libres, les foncteurs, les lambdas et tout les trucs aux quel je n'ai pas pensé qui s'appellent comme des fonctions? - Comment je récupère le type des arguments de la fonction que j'ai passé pour le donner à get_data - get_data renvoie un tuple, est ce que je peux le "déplier" pour qu'il ressemble a un paquet d'arguments classiques? (si non, existe t'il une solution qui suppose que la fonction utilisateur prend un tuple de n'importe quoi?.
//j'ai par exemple
bool f(int i){std::cout << "f "<<i<<"\n";}
auto lambda=[](std::string s, int i){std::cout << "lambda" <<s <<" "<<i<<"\n";}
struct fonct{bool operator()(int i){std::cout << "fonct "<<i<<"\n";}
//je voudrai pouvoir faire
apply("select age from personne",f1);
apply("select nom,age from personne",lambda);
apply("select age from personne",fonct );
Voila ma proposition, qui ne marche pas
//Je galère pour écrire le code template qui fait ca
template<bool Fn(Args...)>// <-- je met quoi ici?
void apply(const std::string & sql, Fn & function){
while(have_data()){
const auto &tuple_data = get_data<Args...>(); //<-- idem, comment je récupère la liste des types à passer.
bool ok = Fn(/*???*/);//<-- je passe quoi?
if(!ok){return false;}
}
return true;
}
int main(int, char **)
{
apply("select age from personne", f);
apply("select nom,age from personne", lambda);
apply("select age from personne", fonct());
}
@bacelar Mon problème pratique est de m'interfacer avec des bases existantes que j'utilise aussi dans d'autres contextes avec d'autres programmes (pour du data mining essentiellement), pas de sauvegarder mes objets dans une base.
@anolya Je sais faire passer une fonction, là où je sèche, c'est pour récupérer les arguments de la fonction, et construire un tuple avec
@jo_link_noir J'ai pas compris comment ta solution marche. Est ce que tu peux m'expliquer s'il te plait. Merci pour la proposition en tout cas. Je compte utiliser ton code pour une lib, est ce que je peux, et est ce que tu veux que je te rajoute aux crédits (si oui, a quel nom?).
J'au aussi tenté de généraliser la structure dispatch_get_data. Voila mon code, j'ai une erreur ligne 10 et je ne comprend pas pourquoi.
Pour apply_from_tuple, ce papier: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3829.pdf
apply_from_tuple prend un tuple (t), un foncteur (f) et optionnellement les indices du tuple à transmettre à la fonction. Si les indices ne sont pas donnés le tuple est entièrement déballé et transmit à f (f(get<0>(t), std::get<1>(t), std::get<N-1>(t)) avec N le nombre d'élément dans le tuple).
param_objet prend un pointeur sur fonction membre et en extrait les paramètres (seule la déclaration importe car la fonction est uniquement utilisée avec decltype). get_tuple_params propage operator() à pram_objet (pour les classes et lambda) et si le type est un pointeur sur fonction en déduit directement les paramètres.
Note que param_objet ne prend pas en compte les fonctions membres volatiles.
Pour ton erreur je pense qu'il faut faire gd.template get_data<Args...>(fn_args...).
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
* Un wrapper C++ pour sqlite * Une alternative a boost units
* Un wrapper C++ pour sqlite * Une alternative a boost units
* Un wrapper C++ pour sqlite * Une alternative a boost units