dynamisches static_assert



  • Hallo,

    ich habe mir mit Lambdas eine Property Klasse gebastelt. Um eine ReadOnly Property zu haben, lässt man einfach den Setter weg. Bisher prüfe ich nun im = operator ob der Setter 0 ist und werfe, falls ja, eine Exception. Nun frage ich mich, ob sich das ganze auch schon zur Compiletime lösen lässt. static_assert kann ich dazu aber nicht verwenden, weil der Ausdruck nur einmal ausgewertet wird. Der Compiler müsste für mich aber jeden Aufruf des =operators getrennt auswerten.
    Gibts es einen Kniff, damit auch sowas möglich ist?

    greetz KN4CK3R



  • Ohne Code nix los.



  • template<typename ValueType>
    class Property
    {
    public:
    	Property()
    	{
    
    	}
    	//---------------------------------------------------------------------------
    	Property(const std::function<ValueType()> &get, const std::function<void(ValueType)> &set)
    	{
    		this->get = get;
    		this->set = set;
    	}
    	//---------------------------------------------------------------------------
    	ValueType operator = (const ValueType& value)
    	{
    		if (!set)
    		{
    			throw 1; //hier
    		}
    
    		set(value);
    
    		return value;
    	}
    	//---------------------------------------------------------------------------
    	operator ValueType()
    	{
    		if (!get)
    		{
    			throw 1; //und hier
    		}
    
    		return get();
    	}
    	//---------------------------------------------------------------------------
    
    private:
    	std::function<ValueType()> get;
    	std::function<void(ValueType)> set;
    };
    

    greetz KN4CK3R



  • Wo soll denn der Setter hinsetten? Und woraus soll der Getter lesen?



  • Irgendwie anders mit Templatespezialisierung vielleicht?
    So:

    template<typename ValueType>
    class write_extend
    {
    public:
        typedef ValueType type;
        typedef std::function<void (type)> setter_functor;
    
        write_extend(setter_functor const & setter) : m_setter(setter) {}
    
        type operator = (type const & value)
        {
            m_setter(value);
            return value;
        }
    
    private:
        setter_functor m_setter;
    };
    
    template<typename ValueType>
    class read_extend
    {
    public:
        typedef ValueType type;
        typedef std::function<type ()> getter_functor;
    
        explicit read_extend(getter_functor const & getter)
        : m_getter(getter)
        { }
    
        operator type()
        {
            return m_getter();
        }
    
    private:
        getter_functor m_getter;
    };
    
    struct read_only_property{};
    struct read_write_property{};
    
    template<typename ValueType, typename AccessTag = read_write_property>
    class property;
    
    template<typename ValueType>
    class property<ValueType, read_write_property> 
        : public read_extend<ValueType>
        , public write_extend<ValueType>
    {
        typedef read_extend<ValueType> read_base;
        typedef write_extend<ValueType> write_base;
    public:
        property(getter_functor const & getter, setter_functor const & setter)
        : read_base(getter)
        , write_base(setter)
        { }
        using read_base::operator read_base::type;
        using write_base::operator=;
    };
    
    template<typename ValueType>
    class property<ValueType, read_only_property> 
        : public read_extend<ValueType>
    {
        typedef read_extend<ValueType> read_base;
    public:
        property(getter_functor const & getter)
        : read_base(getter)
        { }
        using read_base::operator read_base::type;
    };
    
    //Benutzung:
    //hat nur setter und kann nur gelesen werden
    property<int, read_only_property> p1(&get_fct);
    //compile fehler: kein setter setzbar
    property<int, read_only_property> p2(&get_fct, &set_fct);
    
    //lesen und schreiben erlaubt
    property<int> p3(&get_fct, &set_fct);
    
    //compile fehler: p1 hat kein operator=
    p1 = 42;
    //okay
    std::cout << p1 << std::endl;
    
    //okay
    p3 = 42;
    //okay
    std::cout << p3 << std::endl;
    

    Ob das ganze überhaupt sinnvoll ist, sei mal dahingestellt...



  • Michael E. schrieb:

    Wo soll denn der Setter hinsetten? Und woraus soll der Getter lesen?

    dazu übergibt man ja den entsprechenden Getter bzw Setter.

    @Tachyon: ok, das wäre ein Möglichkeit, danke

    greetz KN4CK3R


  • Administrator

    Wie wäre es ganz banal mit einer ReadOnlyProperty Klasse?

    Grüssli



  • geht natürlich, eine "ist ReadOnly" Meldung beim Compilieren hätte mir persönlich allerdings besser gefallen.

    greetz KN4CK3R


  • Administrator

    KN4CK3R schrieb:

    geht natürlich, eine "ist ReadOnly" Meldung beim Compilieren hätte mir persönlich allerdings besser gefallen.

    class read_only_property
    {
    public:
      read_only_property& operator =(int value)
      {
        static_assert(false, "property is readonly");
      }
    };
    
    int main()
    {
      read_only_property p;
    
      p = 10;
    
      return 0;
    }
    

    Noch ein Wunsch?

    Grüssli



  • nein, passt 😉


Anmelden zum Antworten