billyquith / ponder

C++ reflection library with Lua binding, and JSON and XML serialisation.
http://billyquith.github.io/ponder/
Other
645 stars 95 forks source link

Class properties do not respect ValueMappers #118

Open iwbnwif opened 5 years ago

iwbnwif commented 5 years ago

Hi, I have been using Ponder V1.x for some years and it has been working very well.

Recently, I have been making some updates to my app and decided to move to Ponder V3.x. Generally this has gone quite smoothly, there are a couple of solvable niggles - I was using tags a lot and also (mistakenly) relying on the class properties to be retrieved in the order in which they are declared.

However, I have one issue that I haven't been able to find a solution for which is the subject of this report.

I am using wxWidgets and therefore wxString in a number of places. The QString example provides a good demonstration for how to achieve this, but it no longer seems to work properly. Probably the best way to explain the problem is an example:

namespace ponder_ext
{
    template <>
    struct ValueMapper<wxString>
    {
        static const ponder::ValueKind kind = ponder::ValueKind::String;

        static ponder::String to(const wxString& source)
        {
            return source.ToStdString();
        }

        template <typename T>
        static wxString from(const T& source)
        {
            return wxString(ValueMapper<ponder::String>::from(source));
        }
    };
}

class Person
{
public:
    const wxString& getName() const { return m_name; }
    void setName(const wxString& name) { m_name = name; }
private:
    wxString m_name;
}

PONDER_TYPE(Person)

static void declare()
{
   ponder::Class::declare<wxString>("wxString");

   ponder::Class::declare<Person>("Person")
        .property("name", &Person::getName, &Person::setName)
        ;
}

static void use()
{
     declare();

     if (ponder::classByTypeSafe<wxString>() != nullptr)
          puts("wxString declared okay"); // works okay

     if (ponder_ext::ValueMapper<wxString>::kind == ponder::ValueKind::String)
         puts("wxString is a string"); // works okay

     ponder::Value value = wxString("Hello");

     if (value.kind() == ponder::ValueKind::String)
          puts("value is a string"); // works okay

   Person harry;

   // Fails to get the right ValueKind here ....
   for (auto&& property : getClassByType<Person>.propertyIterator())
   {
       switch (property.value()->kind())
       {
       ....

       case::ValueKind::User:
            puts("property is a User value kind"); // always selects here, but should be ValueKind::String :(
}

I can work around this by converting wxString to std::string everywhere, but first I wanted to check that I am not making a mistake or it is a simple bug in Ponder that can be easily fixed.

iwbnwif commented 5 years ago

Sorry, just to add I am using MingGW-W64 (x86_64-posix-seh-rev0) version 8.1.0 on Windows.