@@ -38,8 +38,8 @@ class ofAbstractParameter {
3838 virtual std::string getEscapedName () const ;
3939 virtual std::string valueType () const = 0;
4040
41- virtual bool isInit () const = 0;
42- virtual void reInit () = 0 ;
41+ virtual bool isInit () const { return true ; }
42+ virtual void reInit () {} ;
4343
4444 virtual void setParent (ofParameterGroup & _parent) = 0;
4545 std::vector<std::string> getGroupHierarchyNames () const ;
@@ -351,6 +351,23 @@ ofReadOnlyParameter<ParameterType, Friend> & ofParameterGroup::getReadOnly(std::
351351/* ! \cond PRIVATE */
352352namespace of {
353353namespace priv {
354+
355+ template <typename T, typename U = T>
356+ constexpr auto test_comparable (int ) -> decltype(std::declval<T>() == std::declval<U>(), std::true_type{});
357+
358+ template <typename T, typename U = T>
359+ constexpr std::false_type test_comparable (...);
360+
361+ template <typename T>
362+ struct is_comparable : decltype (test_comparable<T>(0 )) {};
363+
364+ template <typename T>
365+ struct is_comparable <std::vector<T>> : is_comparable<T> {};
366+
367+ template <typename T>
368+ constexpr bool is_comparable_v = is_comparable<T>::value;
369+
370+
354371// ----------------------------------------------------------------------
355372// Mechanism to provide min and max default values for types where it makes sense
356373template <typename T, bool B>
@@ -510,6 +527,9 @@ template <typename ParameterType>
510527class ofParameter : public ofAbstractParameter {
511528public:
512529
530+ // / \brief flag to opt-out of the isInit mechanism (in-complement to auto-detection of incomparability)
531+ static inline bool init_opt_out { false };
532+
513533 // / \brief constructs a default ofParameter of type ParameterType
514534 // / \tparam ParameterType the type of the Value held by the ofParameter
515535 ofParameter ();
@@ -601,6 +621,8 @@ class ofParameter : public ofAbstractParameter {
601621 void makeReferenceTo (ofParameter<ParameterType> & mom);
602622
603623 ofParameter<ParameterType> & operator =(const ofParameter<ParameterType> & v);
624+
625+ template <typename U = ParameterType, std::enable_if_t <!std::is_same_v<U, ofParameter<U>>, int > = 0 >
604626 const ParameterType & operator =(const ParameterType & v);
605627
606628 template <typename U = ParameterType>
@@ -671,39 +693,38 @@ class ofParameter : public ofAbstractParameter {
671693protected:
672694private:
673695 class Value {
696+ auto init_init (ParameterType &v) {
697+ if constexpr (of::priv::is_comparable_v<ParameterType>) {
698+ if (!init_opt_out) init = v;
699+ }
700+ }
701+
674702 public:
675703 Value ()
676- : init(of::priv::TypeInfo<ParameterType>::min())
677- , min(of::priv::TypeInfo<ParameterType>::min())
704+ : min(of::priv::TypeInfo<ParameterType>::min())
678705 , max(of::priv::TypeInfo<ParameterType>::max())
679706 , bInNotify(false )
680- , serializable(true ) { }
681-
707+ , serializable(true ) { init_init (min); }
682708 Value (ParameterType v)
683- : init(v)
684- , value(v)
709+ : value(v)
685710 , min(of::priv::TypeInfo<ParameterType>::min())
686711 , max(of::priv::TypeInfo<ParameterType>::max())
687712 , bInNotify(false )
688- , serializable(true ) { }
689-
713+ , serializable(true ) { init_init (v); }
690714 Value (std::string name, ParameterType v)
691715 : name(name)
692- , init(v)
693716 , value(v)
694717 , min(of::priv::TypeInfo<ParameterType>::min())
695718 , max(of::priv::TypeInfo<ParameterType>::max())
696719 , bInNotify(false )
697- , serializable(true ) { }
698-
720+ , serializable(true ) { init_init (v); }
699721 Value (std::string name, ParameterType v, ParameterType min, ParameterType max)
700722 : name(name)
701- , init(v)
702723 , value(v)
703724 , min(min)
704725 , max(max)
705726 , bInNotify(false )
706- , serializable(true ) { }
727+ , serializable(true ) { init_init (v); }
707728
708729 std::string name;
709730 ParameterType init, value, min, max;
@@ -762,9 +783,10 @@ inline ofParameter<ParameterType> & ofParameter<ParameterType>::operator=(const
762783}
763784
764785template <typename ParameterType>
786+ template <typename U, std::enable_if_t <!std::is_same_v<U, ofParameter<U>>, int >>
765787inline const ParameterType & ofParameter<ParameterType>::operator =(const ParameterType & v) {
766788 set (v);
767- return obj-> value ;
789+ return * this ;
768790}
769791
770792template <typename ParameterType>
@@ -891,7 +913,13 @@ ParameterType ofParameter<ParameterType>::getMax() const {
891913
892914template <typename ParameterType>
893915void ofParameter<ParameterType>::setInit(const ParameterType & init) {
894- obj->init = init;
916+ if constexpr (of::priv::is_comparable_v<ParameterType>) {
917+ if (!init_opt_out) {
918+ obj->init = init;
919+ return ;
920+ }
921+ }
922+ ofLogWarning (" ofParameter::setInit" ) << " called on a non-comparable (or opted-out) type" ;
895923}
896924
897925template <typename ParameterType>
@@ -901,12 +929,24 @@ ParameterType ofParameter<ParameterType>::getInit() const {
901929
902930template <typename ParameterType>
903931bool ofParameter<ParameterType>::isInit() const {
904- return obj->value == obj->init ;
932+ if constexpr (of::priv::is_comparable_v<ParameterType>) {
933+ if (!init_opt_out) {
934+ return obj->value == obj->init ;
935+ }
936+ }
937+ ofLogWarning (" ofParameter::isInit" ) << " called on a non-comparable (or opted-out) type => always true" ;
938+ return true ;
905939}
906940
907941template <typename ParameterType>
908942void ofParameter<ParameterType>::reInit() {
909- setMethod (obj->init );
943+ if constexpr (of::priv::is_comparable_v<ParameterType>) {
944+ if (!init_opt_out) {
945+ setMethod (obj->init );
946+ return ;
947+ }
948+ }
949+ ofLogWarning (" ofParameter::reInit" ) << " called on a non-comparable (or opted-out) type => no-op" ;
910950}
911951
912952template <typename ParameterType>
@@ -1276,9 +1316,6 @@ class ofReadOnlyParameter : public ofAbstractParameter {
12761316
12771317 void setMin (const ParameterType & min);
12781318 void setMax (const ParameterType & max);
1279- void setInit (const ParameterType & init);
1280- bool isInit () const ;
1281- void reInit ();
12821319
12831320 void fromString (const std::string & str);
12841321
@@ -1560,27 +1597,6 @@ inline void ofReadOnlyParameter<ParameterType, Friend>::setMax(const ParameterTy
15601597 parameter.setMax (max);
15611598}
15621599
1563- template <typename ParameterType, typename Friend>
1564- inline void ofReadOnlyParameter<ParameterType, Friend>::setInit(const ParameterType & init) {
1565- parameter.setInit (init);
1566- }
1567-
1568- template <typename ParameterType, typename Friend>
1569- inline bool ofReadOnlyParameter<ParameterType, Friend>::isInit() const {
1570- // not sure what the expected behaviour for isInit() would be for ReadOnlyParameter
1571- // as-is, it fails with : No member named 'value' in 'ofParameter<std::string>'
1572- // returning true while informing with a log msg seems sane
1573- ofLogVerbose (" ofReadOnlyParameter::isInit()" ) << " isInit() called on ofReadOnlyParameter, where it always returns true" ;
1574- return true ;
1575- }
1576-
1577- template <typename ParameterType, typename Friend>
1578- inline void ofReadOnlyParameter<ParameterType, Friend>::reInit() {
1579- // not sure what the expected behaviour for reInit() would be for ReadOnlyParameter
1580- // informing with a log msg seems sane
1581- ofLogVerbose (" ofReadOnlyParameter::reInit()" ) << " reInit() called on ofReadOnlyParameter, where it is a no-op" ;
1582- }
1583-
15841600template <typename ParameterType, typename Friend>
15851601inline void ofReadOnlyParameter<ParameterType, Friend>::fromString(const std::string & str) {
15861602 parameter.fromString (str);
0 commit comments