Unklarheiten im Bezug auf überladene Operatoren



  • Hoi,
    ich möchte Boost.PropertyTree mit eigenen Werttypen nutzen und möchte deswegen Übersetzer implementieren. Das Ganze möchte ich über Streams abwickeln.

    Nur was stimmt an meinem Ansatz nicht? (Denke der Sourcecode bedarf keiner Erklärung)

    // C++ Standard Library:
    #include <string>
    #include <sstream>
    
    // Boost:
    #include <boost/optional.hpp>
    
    namespace Synthetic
    {
        namespace Util
        {
            template<typename Char, typename External>
            struct StreambasedPropertyTranslator
            {
                typedef std::basic_string<Char> internal_type;
                typedef External external_type;
    
                boost::optional<external_type> get_value(internal_type const& str)
                {
                    if (!str.empty())
                    {
                        external_type val;
                        std::basic_stringstream<Char> stream(str);
                        stream >> val;
                        if(stream)
                            return boost::optional<external_type>(val);
                    }
    
                    return boost::optional<external_type>(boost::none);
                }
    
                boost::optional<internal_type> put_value(external_type const& b)
                {
                    std::basic_stringstream<Char> stream;
                    stream << b;
                    if(stream)
                        return boost::optional<internal_type>(stream.str());
                    else
                        return boost::optional<internal_type>(boost::none);
                }
            };
        }
    }
    
    // C++ Standard Library:
    #include <istream>
    #include <ostream>
    #include <limits>
    
    // SFML:
    #include <SFML/System/Vector2.hpp>
    
    // Synthetic:
    #include "StreambasedPropertyTranslator.hpp"
    
    namespace Synthetic
    {
        namespace Util
        {
            // Syntax: (Value1, Value2)
    
            template<typename ValueT>
            std::basic_istream<char>& operator<<(std::basic_istream<char>& in,
                sf::Vector2<ValueT>& out)
            {
                // Eat '('.
                in.ignore(std::numeric_limits<std::streamsize>::max(), '(');
    
                // Read first value.
                in >> out.x;
    
                // Eat ','.
                in.ignore(std::numeric_limits<std::streamsize>::max(), ',');
    
                // Read second value.
                in >> out.y;
    
                // Eat ')'.
                return in.ignore(std::numeric_limits<std::streamsize>::max(), ')');
            }
    
            template<typename ValueT>
            std::basic_ostream<char>& operator<<(std::basic_ostream<char>& out,
                sf::Vector2<ValueT> const& in)
            {
                return out << '(' << in.x << ", " << in.y << ')';
            }
        }
    }
    
    namespace boost
    {
        namespace property_tree
        {
            template<typename CharT, typename ValueT>
            struct translator_between<
                std::basic_string<CharT>, sf::Vector2<ValueT>>
            {
                typedef Synthetic::Util::StreambasedPropertyTranslator<
                    CharT, sf::Vector2<ValueT>> type;
            };
        }
    }
    

    Anwendung im Code dann wie folgt:

    config.get<sf::Vector2<float>>("Object1.Center");
    

    Mir ist bewusst dass ich die Stream-Operatoren erst nach dem StreambasedPropertyTranslator definiere, aber da StreambasedPropertyTranslator ein Klassentemplate ist sollte das doch trotzdem so funktionieren?

    Der Compiler beschwert sich jedenfalls über das Streamen in val hier, nämlich dass er keinen operator>> findet:

    ...
    external_type val;
    std::basic_stringstream<Char> stream(str);
    stream >> val;
    ...
    


  • Holy Shit, da überlege ich mir ne halbe Ewigkeit was an meinem Konzept nicht stimmt und jetzt sehe ich dass ich ausversehen 2x operator<< geschrieben habe ... warum fällt mir soetwas erst auf nachdem ich es ins Forum gepostet habe?



  • Edit: Und schon wieder zum Affen gemacht, es lag an PropertyTree ... heute ist echt nicht mein Tag.

    Ist zwar jetzt Offtopic, aber damit der Thread irgendeinen Sinn hat:

    template<typename ValueT>
            std::basic_istream<char>& operator>>(std::basic_istream<char>& in,
                sf::Vector2<ValueT>& out)
            {
                // Eat '('.
                in.ignore(std::numeric_limits<std::streamsize>::max(), '(');
                assert(in);
    
                // Read first value.
                in >> out.x;
                assert(in);
    
                // Eat ','.
                in.ignore(std::numeric_limits<std::streamsize>::max(), ',');
                assert(in);
    
                // Read second value.
                in >> out.y;
                assert(in);
    
                // Eat ')'.
                return in.ignore(std::numeric_limits<std::streamsize>::max(), ')');
            }
    

    Warum knallt das beim zweiten Wert wenn der Inputstream "(10, 10)" ist?

    Danke und Grüße,
    Ethon


Anmelden zum Antworten