> QObject::bind(sender, &Sender::signalName, receiver, &Receiver::setter);
> This is exactly connect() we already have. I think that bind adds one more step : it does the set. ie. bind would be : QObject::bind(sender, &Sender::signalName, &Sender::getter, receiver, &Receiver::setter); and would be equivalent to : QObject::connect(sender, &Sender::signalName, receiver, &Receiver::setter); receiver->setter(sender->getter()); Now, about the overall string problem, I think that most people would rather do : QObject::bind(sender, "source", receiver, "target"); And actually, with modern C++, this can be made typesafe : for instance the boost.metaparse guys are able to convert (constexpr) strings to types : http://www.boost.org/doc/libs/1_63_0/doc/html/metaparse.html at compile time. So it would not be unthinkable to have moc generate the appropriate parser and "compile-time property" class At the end of this mail there is an example implementation (that uses a string literal from boost.hana) and allows to do the following at compile-time: (requires c++17; I tested with clang 4 and I believe gcc 7 would work) bind(sender, "source"_s, receiver, "compatibleTarget"_s); While this won't compile bind(sender, "source"_s, receiver, "incompatibleTarget"_s); So the SIGNAL() and SLOT() macros could maybe be modified this way (Qt6 anyone ? ;p) to have compile-checked versions (SSIGNAL() / SSLOT()). #include <string> #include <type_traits> #define BOOST_HANA_CONFIG_ENABLE_STRING_UDL #include <boost/hana.hpp> #include <boost/hana/string.hpp> using namespace boost::hana::literals; template<typename Param1, typename Param2> static const constexpr bool constructible = std::is_constructible<typename Param2::type, typename Param1::type>::value; template<typename Param1, typename Param2> using is_compatible = std::enable_if_t<std::is_constructible<typename Param2::type, typename Param1::type>::value>; template<typename Param1, typename Param2> using not_compatible = std::enable_if_t<!std::is_constructible<typename Param2::type, typename Param1::type>::value>; class foo { public: int getProp1() { return 0; } void setProp1(int) { } void notifyProp1(int); std::string getProp2() { return ""; } void setProp2(std::string) { } void notifyProp2(std::string); // Generate the following struct / functions with moc // or send a bottle of champagne + chocolates to ~ogoffart to put it in Verdigris and // integrate it with W_PROPERTY struct foo_prop1 { using type = int; static const constexpr auto name = "prop1"_s; static const constexpr auto getter = &foo::getProp1; static const constexpr auto setter = &foo::setProp1; static const constexpr auto notifier = &foo::setProp1; }; struct foo_prop2 { using type = std::string; static const constexpr auto name = "prop2"_s; static const constexpr auto getter = &foo::getProp2; static const constexpr auto setter = &foo::setProp2; static const constexpr auto notifier = &foo::setProp2; }; template<typename T1, typename Param1, typename T2, typename Str2> static constexpr void bind_receiver(T1& obj1, const Param1&, T2& obj2, Str2 str2) { if constexpr (str2 == foo_prop1::name) { (obj2.*foo_prop1::setter)((obj1.*Param1::getter)()); } else if constexpr(str2 == foo_prop2::name) { (obj2.*foo_prop2::setter)((obj1.*Param1::getter)()); } } template<typename T1, typename Str1, typename T2, typename Str2> static constexpr void bind_sender(T1& obj1, Str1 str1, T2& obj2, Str2 str2) { if constexpr (str1 == foo_prop1::name) { obj2.bind_receiver(obj1, foo_prop1{}, obj2, str2); } else if constexpr (str1 == foo_prop2::name) { obj2.bind_receiver(obj1, foo_prop2{}, obj2, str2); } } template<typename Param1, typename Str2> static constexpr bool can_bind_receiver() { if constexpr (Str2{} == foo_prop1::name) { return constructible<foo_prop1, Param1>; } else if constexpr(Str2{} == foo_prop2::name) { return constructible<foo_prop2, Param1>; } else { return false; } } template<typename Str1, typename T2, typename Str2> static constexpr bool can_bind_sender() { if constexpr (Str1{} == foo_prop1::name) { return T2::template can_bind_receiver<foo_prop1, Str2>(); } else if constexpr (Str1{} == foo_prop2::name) { return T2::template can_bind_receiver<foo_prop2, Str2>(); } else { return false; } } }; template<typename T1, typename Str1, typename T2, typename Str2> constexpr void bind(T1& obj1, Str1 str1, T2& obj2, Str2 str2) { static_assert(T1::template can_bind_sender<Str1, T2, Str2>(), "The types are not compatible"); T1::bind_sender(obj1, str1, obj2, str2); } int main() { foo f1; foo f2; bind(f1, "prop1"_s, f2, "prop1"_s); // works // bind(f1, "prop1"_s, f2, "prop2"_s); // does not compile return 0; } Best, ------- Jean-Michaël Celerier http://www.jcelerier.name On Wed, Mar 22, 2017 at 8:13 AM, Prashanth Udupa <prashanth.ud...@gmail.com> wrote: > Hi Thiago, > > >> But let me put it this way: will not accept new text-based API for signal, >> slots and properties in QObject. You can do that externally, as you've >> done >> it, but I won't take it in QtCore. > > > Ok. > > >> So we need the compile-time checking. What can we use to identify the >> property >> changing? A read-only property that changes has two C++ identifiers: the >> getter >> and the notify signal. And what can we use to identify the receiving >> property? > > I agree, QObject API should ideally have compile time checks rather than > runtime debug dumps or bool isValid()s. > >> The getter and the setter. >> So this new functionality would be: >> QObject::bind(sender, &Sender::signalName, receiver, >> &Receiver::setter); >> This is exactly connect() we already have. >> > > True. Makes sense. > > Thanks, > Prashanth > > > On Wed, Mar 22, 2017 at 12:19 PM, Thiago Macieira < > thiago.macie...@intel.com> wrote: > >> Em terça-feira, 21 de março de 2017, às 22:58:38 PDT, Thiago Macieira >> escreveu: >> > Em terça-feira, 21 de março de 2017, às 19:38:19 PDT, Prashanth Udupa >> > >> > escreveu: >> > > QSlider *slider = ... >> > > QLabel *label = .... >> > > QObject::bind(slider, "value", label, "text”); >> > >> > This is a bad example because "text" is a string and would require a >> > conversion. But let's say we're connecting a slider to a QProgressBar. >> You >> > can just write: >> > >> > QObject::connect(slider, &QSlider:valueChanged, >> > &progressBar, &QProgressBar::setValue); >> >> And your other example: >> >> > QSlider *slider = .... >> > QLabel *label = .... >> > QObject::bind(slider, "value", label, "text", [](const QVariant &v) { >> return >> > v.toInt()*2; }); >> >> Would be: >> >> QObject::connect(slider, &QSlider::valueChanged, &label, [label](int >> value) { >> label->setText(QString::number(value * 2)); >> }); >> >> But let me put it this way: will not accept new text-based API for signal, >> slots and properties in QObject. You can do that externally, as you've >> done >> it, but I won't take it in QtCore. >> >> So we need the compile-time checking. What can we use to identify the >> property >> changing? A read-only property that changes has two C++ identifiers: the >> getter >> and the notify signal. And what can we use to identify the receiving >> property? >> The getter and the setter. >> >> So this new functionality would be: >> >> QObject::bind(sender, &Sender::signalName, receiver, >> &Receiver::setter); >> >> This is exactly connect() we already have. >> >> -- >> Thiago Macieira - thiago.macieira (AT) intel.com >> Software Architect - Intel Open Source Technology Center >> >> _______________________________________________ >> Interest mailing list >> Interest@qt-project.org >> http://lists.qt-project.org/mailman/listinfo/interest >> > > > > -- > Thanks and Warm Regards, > Prashanth N Udupa > URL: http://www.prashanthudupa.com > > Scan the QR Code below using KitApp > <https://play.google.com/store/apps/details?id=me.kitapp.kitapp> for > Android & message me on my phone without revealing your phone number! > > > > _______________________________________________ > Interest mailing list > Interest@qt-project.org > http://lists.qt-project.org/mailman/listinfo/interest > >
_______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest