IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Variadic explode retournant un tuple (avec cast !)


Sujet :

Langage C++

  1. #1
    Membre régulier
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Points : 99
    Points
    99
    Par défaut Variadic explode retournant un tuple (avec cast !)
    Bonjour !

    Je cherche à faire un explode sur un string, et que chaque partie coupée du string, soit castée vers un type voulu, (si aucun type n'est donné, le type retourné sera un simple std::string.

    Donc, pour commencer, il faut connaitre le nombre de cast voulus, et les types voulus (en variadic)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        template<int NCasts, typename... Casts>
        static const std::tuple<int, Casts...> explode(const std::string& str, const char separator)
        {
            return explode_impl<std::string, NCasts, Casts...>::call(str, separator);
        }
    Du coup, si l'utilisateur donne NCasts = 0, on ne fera aucun cast et la fonction retournera un std::tuple< std::string ... >
    Ce qui donne, version 1 : avec cast, version 2: NCasts = 0:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    // v1
        template<typename String, int NCasts, typename... Casts>
        struct explode_impl
        {
            static const std::tuple<int, Casts...> call(const String& str, const char separator)
            {
                std::string buffer;
                std::tuple<decltype(NCasts), Casts...> result;
                decltype(NCasts) i = 0;
                while(++i < NCasts) result = std::tuple_cat(result, explode_call_impl<String, decltype(nth_argument<const_cast<decltype(i)>(i), Casts...>::value)>::call(buffer, str, separator));
                std::get<0>(result) = NCasts;
                return result;
            }
        };
    // v2
        template<typename String, typename... Casts>
        struct explode_impl<String, 0, Casts...>
        {
            static const std::tuple<int, Casts...> call(const String& str, const char separator)
            {
                std::string buffer;
                std::tuple<int, Casts...> result = std::make_tuple<int, Casts...>(0);
                for(int& i = std::get<0>(result);
                    ;
                    ++i)
                {
                    if(!std::getline(str, buffer, separator)) break;
                    result = std::tuple_cat(result, buffer);
                }
                return result;
            }
        };
    Ensuite, il manque le découpage et le cast... pour le cas général, et le cas std::string (Au cas ou l'utilisateur demande par exemple std::tuple<int, string, long>)
    Donc...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
        template<typename String, typename Cast>
        struct explode_call_impl
        {
            static const Cast call(std::string& buffer, const String& str, const char separator)
            {
                if(!std::getline(str, buffer, separator)) return;
                std::istringstream temp_ss(buffer);
                Cast casted;
                temp_ss >> casted;
                return casted;
            }
        };
        template<typename String>
        struct explode_call_impl<String, std::string>
        {
            static const std::string call(std::string& buffer, const String& str, const char separator)
            {
                if(!std::getline(str, buffer, separator)) return;
                return buffer;
            }
        };
    Il vous faudra également nth_argument, alors le voici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    	template<int N, typename T, T... Args>
    	struct nth_argument
    	{
    	    static constexpr T values[sizeof...(Args)] = {Args...};
    	    static const T value = values[N];
    	};
        template<int N, typename T, T... Args>
        constexpr T nth_argument<N, T, Args...>::values[sizeof...(Args)];
    De loin ca à l'air bien, mais le compilo n'est pas d'accord!

    /media/data/dev/projects/test/test_type/../../Tools/tools.h: In instantiation of ‘const std::tuple<int, Casts ...> tools::explode(const string&, char) [with int NCasts = 0; Casts = {}; std::string = std::basic_string<char>]’:
    /media/data/dev/projects/test/test_type/main.cpp:9:83: required from here
    /media/data/dev/projects/test/test_type/../../Tools/tools.h:52:84: error: no matching function for call to ‘variadic::explode_impl<std::basic_string<char>, 0>::explode_impl(const string&, const char&)’
    return variadic::explode_impl<std::string, NCasts, Casts...>(str, separator);
    ^
    /media/data/dev/projects/test/test_type/../../Tools/tools.h:52:84: note: candidates are:
    In file included from /media/data/dev/projects/test/test_type/../../Tools/tools.h:7:0,
    from /media/data/dev/projects/test/test_type/main.cpp:2:
    /media/data/dev/projects/test/test_type/../../Tools/variadic.h:97:12: note: constexpr variadic::explode_impl<std::basic_string<char>, 0>::explode_impl()
    struct explode_impl<String, 0, Casts...>
    ^
    /media/data/dev/projects/test/test_type/../../Tools/variadic.h:97:12: note: candidate expects 0 arguments, 2 provided
    /media/data/dev/projects/test/test_type/../../Tools/variadic.h:97:12: note: constexpr variadic::explode_impl<std::basic_string<char>, 0>::explode_impl(const variadic::explode_impl<std::basic_string<char>, 0>&)
    /media/data/dev/projects/test/test_type/../../Tools/variadic.h:97:12: note: candidate expects 1 argument, 2 provided
    /media/data/dev/projects/test/test_type/../../Tools/variadic.h:97:12: note: constexpr variadic::explode_impl<std::basic_string<char>, 0>::explode_impl(variadic::explode_impl<std::basic_string<char>, 0>&&)
    /media/data/dev/projects/test/test_type/../../Tools/variadic.h:97:12: note: candidate expects 1 argument, 2 provided
    Quelqu'un saurait me dire ce qui cloche ?

    Merci d'avance

    nico

  2. #2
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par DakM Voir le message
    Quelqu'un saurait me dire ce qui cloche ? :mrgreen
    Hello,

    A première vue, plusieurs choses bizzare :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    template<typename String, typename Cast>
    struct explode_call_impl
    {
    	static const Cast call(std::string& buffer, const String& str, const char separator)
    	{
    		if(!std::getline(str, buffer, separator)) return;
    		// ...
    	}
    };
    template<typename String>
    struct explode_call_impl<String, std::string>
    {
    	static const std::string call(std::string& buffer, const String& str, const char separator)
    	{
    		if(!std::getline(str, buffer, separator)) return;
    		return buffer;
    	}
    };
    Des fonctions qui devraient retourner quelque chose, mais qui ne retournent rien.

    Pour le reste, me faut un peu plus de temps ^^"

    edit :
    Du mal à m'y retrouver dans tous ces templates, j'ai repris le code à 0 et j'arrive à quelques chose de beaucoup plus simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    template <class... Types>
    struct explode_impl;
     
    template <class T, class... Types>
    struct explode_impl<T, Types...> {
    	static std::tuple<T, Types...> call(std::istream& is, const char delimiter) {
    		// fixer l'ordre d'appel et recursion
    		const auto& tmp = explode_impl<T>::call(is, delimiter);
    		return std::tuple_cat(tmp, explode_impl<Types...>::call(is, delimiter));
    	}
    };
     
    template <class T>
    struct explode_impl<T> {
    	static std::tuple<T> call(std::istream& str, const char delimiter) {
    		// get item
    		std::string buffer;
    		if(!std::getline(str, buffer, delimiter)) {
    			throw std::exception();
    		}
    		T t;
    		std::istringstream ss(buffer);
    		if(!(ss >> t)) {
    			throw std::exception();
    		}
    		return std::make_tuple(t);
    	}
    };
     
    template <class... Types>
    std::tuple<Types...> explode(const std::string& str, const char delimiter) {
    	std::istringstream is(str);
    	return explode_impl<Types...>::call(is, delimiter);
    }
    Je continue à chercher le problème dans ton code.

  3. #3
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    J'avais oublié le fait de pouvoir ne pas fournir de types
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    template <int N, class... Args>
    struct tuple_string_repeat {
    	typedef typename tuple_string_repeat<N-1, std::string, Args...>::type type;
    };
     
    template <class... Args>
    struct tuple_string_repeat<0, Args...> {
    	typedef std::tuple<Args...> type;
    };
     
    template <class... Types>
    struct explode_impl;
     
    template <class T, class... Types>
    struct explode_impl<T, Types...> {
    	static std::tuple<T, Types...> call(std::istream& is, const char delimiter) {
    		// fixer l'ordre d'appel et recursion
    		const auto& tmp = explode_impl<T>::call(is, delimiter);
    		return std::tuple_cat(tmp, explode_impl<Types...>::call(is, delimiter));
    	}
    };
     
    template <class T>
    struct explode_impl<T> {
    	static std::tuple<T> call(std::istream& str, const char delimiter) {
    		// get item
    		std::string buffer;
    		if(!std::getline(str, buffer, delimiter)) {
    			throw std::exception();
    		}
    		T t;
    		std::istringstream ss(buffer);
    		if(!(ss >> t)) {
    			throw std::exception();
    		}
    		return std::make_tuple(t);
    	}
    };
     
     
    template <int N>
    struct explode_impl_string {
    	static typename tuple_string_repeat<N>::type call(std::istream& str, const char delimiter) {
    		// get item
    		std::string buffer;
    		if(!std::getline(str, buffer, delimiter)) {
    			throw std::exception();
    		}
    		std::string t;
    		std::istringstream ss(buffer);
    		if(!(ss >> t)) {
    			throw std::exception();
    		}
    		const auto& tmp = std::make_tuple(t);
    		return std::tuple_cat(tmp, explode_impl_string<N-1>::call(str, delimiter));
    	}
    };
     
    template <>
    struct explode_impl_string<1> {
    	static tuple_string_repeat<1>::type call(std::istream& str, const char delimiter) {
    		// get item
    		std::string buffer;
    		if(!std::getline(str, buffer, delimiter)) {
    			throw std::exception();
    		}
    		std::string t;
    		std::istringstream ss(buffer);
    		if(!(ss >> t)) {
    			throw std::exception();
    		}
    		return std::make_tuple(t);
    	}
    };
     
    template <>
    struct explode_impl_string<0> {
    	static std::tuple<> call(std::istream&, const char) {
    		return std::tuple<>();
    	}
    };
     
    template <class... Types>
    std::tuple<Types...> explode(const std::string& str, const char delimiter) {
    	std::istringstream is(str);
    	return explode_impl<Types...>::call(is, delimiter);
    }
     
    template <int N>
    typename tuple_string_repeat<N>::type explode(const std::string& str, const char delimiter) {
    	std::istringstream is(str);
    	return explode_impl_string<N>::call(is, delimiter);
    }
     
    int main() {
    	std::string s("123 str 42.4f");
    	try {
    		auto t = explode<int, std::string, float>(s, ' ');
    		auto t2 = explode<3>(s, ' ');
    	}
    	catch(...) {	}
     
    	return 0;
    }
    Pour ton code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    std::tuple<decltype(NCasts), Casts...> result;
    decltype(NCasts) i = 0;
    while(++i < NCasts) {
    	result = std::tuple_cat(result, explode_call_impl<String, decltype(nth_argument<const_cast<decltype(i)>(i), Casts...>::value)>::call(buffer, str, separator));
    }
    Pas mal de problèmes ici :
    - une mauvaise utilisation de tuple_cat, tuple_cat génère un tuple du type nécessaire à contenir tous ses paramètres, tu peux pas avoir result = std::tuple_cat(result, ...);, car result ne peut pas être un tuple qui contient tous ses types, plus d'autres (je sais pas si c'est très clair ). Pas besoin de while pour générer le tuple, une récursion de template est necéssaire.
    - str perd son const qualifier
    - nth_argument n'a pas d'opérateur (), tu voulais probablement utiliser [] ?
    - il ne suffit pas de const_cast une variable pour la transformer en constante de compilation

  4. #4
    Membre régulier
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Points : 99
    Points
    99
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Pas mal de problèmes ici :
    - une mauvaise utilisation de tuple_cat, tuple_cat génère un tuple du type nécessaire à contenir tous ses paramètres, tu peux pas avoir result = std::tuple_cat(result, ...);, car result ne peut pas être un tuple qui contient tous ses types, plus d'autres (je sais pas si c'est très clair ). Pas besoin de while pour générer le tuple, une récursion de template est necéssaire.
    - str perd son const qualifier
    - nth_argument n'a pas d'opérateur (), tu voulais probablement utiliser [] ?
    - il ne suffit pas de const_cast une variable pour la transformer en constante de compilation
    Pour tuple_cat, en effet, j'avais lu cela il y a une heure, c'est dommage ^^
    Ensuite, nth_argument ? Pas compris, probablement une faute de frappe
    Et finalement, le const_cast sur la variable i, en effet belle gourde

    Ton code fonctionne parfaitement, à l'exception d'une chose, mais pas sur que cela soit possible!

    Est-il possible d'avoir un:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    auto t = explode<0>(str, delim);
    Et que le template eclate le string autant qu'il peut ?
    Car la, dans le cas ou l'on ne connait pas le nombre de substring, il faut compter le nombre d'occurences de delim, avant d'eclater la chaine!

    merci, nico

  5. #5
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par DakM Voir le message
    Ensuite, nth_argument ? Pas compris, probablement une faute de frappe
    Oui,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nth_argument<const_cast<decltype(i)>(i)
    en relisant ça en écrivant mon post, j'ai cru à un appel à nth_argument<...>(i); ^^"

    Citation Envoyé par DakM Voir le message
    Est-il possible d'avoir un:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    auto t = explode<0>(str, delim);
    Et que le template eclate le string autant qu'il peut ?
    En retournant un std::vector c'est possible, retourner un tuple est par contre impossible. On ne sait pas à la compilation le nombre de string retournés, donc on ne connait pas le type du tuple.

    Il est surement possible de retourner un tuple si le string à découper est une constante de compilation (constexpr).

  6. #6
    Membre régulier
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Points : 99
    Points
    99
    Par défaut
    Donc il est impossible de faire quelque chose du genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int z = count(str, chr);
    auto t = explode<z>(str, chr);
    Comment on pourrais outrepasser ce probleme, tout en ayant la meme flexibilité de retour (c.a.d, un conteneur, avec des types differents, le tuple est juste pratique dans ce cas la.) ?

  7. #7
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par DakM Voir le message
    Donc il est impossible de faire quelque chose du genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int z = count(str, chr);
    auto t = explode<z>(str, chr);
    Comment on pourrais outrepasser ce probleme, tout en ayant la meme flexibilité de retour (c.a.d, un conteneur, avec des types differents, le tuple est juste pratique dans ce cas la.) ?
    Tu peux avoir ce genre de chose si tu ne veux pas un tuple au final pour ce cas la. Un vector fait ici très bien l'affaire, vu que tous tes éléments sont du même type.
    Quand tout n'est pas connu à la compilation, les templates ne sont pas utilisables.

    Tu peux très bien avoir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    std::string s("123 str 42.4f");
    auto t = explode<int, std::string, float>(s, ' '); // t => std::tuple<int, std::string, float>
    auto t2 = explode<3>(s, ' ');	// t2 => std::tuple<std::string, std::string, std::string>,
    								// t2 pourrait aussi etre un std::array<3, std::string> qui serait peut être plus adéquat
    auto v = explode<0>(s, ' '); // v => std::vector<std::string>
    auto v2 = explode(s, ' '); // v2 => std::vector<std::string>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    template <int N, class... Args>
    struct tuple_string_repeat {
    	typedef typename tuple_string_repeat<N-1, std::string, Args...>::type type;
    };
     
    template <class... Args>
    struct tuple_string_repeat<1, Args...> {
    	typedef std::tuple<std::string, Args...> type;
    };
     
    template <class... Args>
    struct tuple_string_repeat<0, Args...> {
    	typedef std::vector<std::string> type;
    };
     
    template <class... Types>
    struct explode_impl;
     
    template <class T, class... Types>
    struct explode_impl<T, Types...> {
    	static std::tuple<T, Types...> call(std::istream& is, const char delimiter) {
    		// fixer l'ordre d'appel et recursion
    		const auto& tmp = explode_impl<T>::call(is, delimiter);
    		return std::tuple_cat(tmp, explode_impl<Types...>::call(is, delimiter));
    	}
    };
     
    template <class T>
    struct explode_impl<T> {
    	static std::tuple<T> call(std::istream& str, const char delimiter) {
    		// get item
    		std::string buffer;
    		if(!std::getline(str, buffer, delimiter)) {
    			throw std::exception();
    		}
    		T t;
    		std::istringstream ss(buffer);
    		if(!(ss >> t)) {
    			throw std::exception();
    		}
    		return std::make_tuple(t);
    	}
    };
     
     
    template <int N>
    struct explode_impl_string {
    	static typename tuple_string_repeat<N>::type call(std::istream& str, const char delimiter) {
    		// fixer l'ordre d'appel et recursion
    		const auto& tmp = explode_impl_string<1>::call(str, delimiter);
    		return std::tuple_cat(tmp, explode_impl_string<N-1>::call(str, delimiter));
    	}
    };
     
    template <>
    struct explode_impl_string<1> {
    	static tuple_string_repeat<1>::type call(std::istream& str, const char delimiter) {
    		// get item
    		std::string buffer;
    		if(!std::getline(str, buffer, delimiter)) {
    			throw std::exception();
    		}
    		return std::make_tuple(buffer);
    	}
    };
     
    template <>
    struct explode_impl_string<0> {
    	static tuple_string_repeat<0>::type call(std::istream& str, const char delimiter) {
    		std::vector<std::string> ret;
    		std::string buffer;
    		while(std::getline(str, buffer, delimiter)) {
    			ret.push_back(buffer);
    		}
    		return ret;
    	}
    };
     
    template <class... Types>
    std::tuple<Types...> explode(const std::string& str, const char delimiter) {
    	std::istringstream is(str);
    	return explode_impl<Types...>::call(is, delimiter);
    }
     
    template <int N>
    typename tuple_string_repeat<N>::type explode(const std::string& str, const char delimiter) {
    	std::istringstream is(str);
    	return explode_impl_string<N>::call(is, delimiter);
    }
     
    tuple_string_repeat<0>::type explode(const std::string& str, const char delimiter) {
    	std::istringstream is(str);
    	return explode_impl_string<0>::call(is, delimiter);
    }
    edit :
    il est aussi possible de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    auto t2 = explode<3, int>(s, ' ');
    // t2 => std::tuple<std::int, std::int, std::int>,
    // t2 pourrait aussi etre un std::array<3, std::int>
    // faut juste le coder, c'est pas grand chose

  8. #8
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    La solution que je t'ai donné sur le chat avec une classe "Conteneur" qui contient des "Element" (contenant en interne un std::string) avec tous les conversions implicites qui vont bien pour faire des choses du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for(Element & e : conteneur)
    {
           int i = e;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    try
    {
           int e = conteneur.next();
           char j = conteneur.next();
          // et/ou
           conteneur >> e >> j;
    } catch(Exception )
    {
               // pas assez d'éléments
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if( conteneur[0].isInteger() )
           int e = conteneur.toInteger();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char * str = conteneur[0].data();
    MaClasse m = deserialize<MaClasse>(conteneur[0].data() );
    conteneur[0] = serialize<MaClasse>(m);
    //on peut aussi envisager d'ajouter un entier à element qui changera selon le type qu'il stocke.
    conteneur[0] = (int)i; // modifie le membre m_type par exemple.
    conteneur[0].type();
    conteneur[0].isType<MaClasse>();
    conteneur[0].getTypeFor<MaClasse>(); // retourne l'identifiant associé pour la classe MaClasse.
    Bref, avec un peu d'imagination tout est possible (et on peut énormément s'amuser).

    Cela ne te conviens pas ? D'après ce que j'avais compris c'est plus ou moins ce que tu cherchais à faire non?
    Il me semble aussi que cette solution serait bien plus souple qu'un tupple (ajout/modification du type d'un élément possible).

  9. #9
    Membre régulier
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Points : 99
    Points
    99
    Par défaut
    @Neckara>
    Pour l'instant cette solution me conviens plutot bien!

    @Iradrille>
    La specialisation pour int N = 1 genere des erreurs, je la vire, je ne pense pas qu'elle soit utile au final, non ?
    Encore une question, serait-il possible, apres avoir recuperer ce tuple<Types...>
    De faire quelque chose du style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class A {*A(type1, type2, etc.......); };
     
    std::vector<A> as;
    for(...)
    {
    auto values = explode<type1, type2, ....>(str, delim);
    as.emplace_back( values );
    }
    Avec une fonction deja existante, std::tie ?

    merci,
    nico

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MySQL] Retourner la date avec un temps supplémentaire
    Par Anduriel dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 19/02/2007, 16h00
  2. retourner en arriere avec fstream
    Par gallvil dans le forum SL & STL
    Réponses: 3
    Dernier message: 09/02/2007, 17h01
  3. [C# 1.1] Comment retourner une ArrayList avec un WS ?
    Par pi05 dans le forum Services Web
    Réponses: 6
    Dernier message: 09/02/2007, 13h00
  4. Retourner une valeur avec Edit
    Par nurbo_2056 dans le forum C++Builder
    Réponses: 6
    Dernier message: 20/12/2006, 14h21
  5. Retourner une valeur avec une fonction
    Par stephtbest dans le forum ASP
    Réponses: 4
    Dernier message: 31/10/2003, 16h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo