Template forward declaration Problem, einfaches Access-Management



  • Hallo,

    Ich einem Programm möchte ich ein sehr einfaches Access Management implementieren. Dieses bekommt die nötigen Rechte per JSON und wandelt diese in eine std::map<int, int> um. Es geht mehr darum den Code möglichst klein zu halten und die Abfrage nach den nötigen Rechten möglichst performant zu halten. Nicht so sehr darum, das die Rechter per Speichermanipulation verändert werden können. Dazu habe ich folgenden Code geschrieben:

    #include <iostream>
    #include <map>
    struct Access {
    
    	static std::map<int, int> bits;
    
    	enum class Group1 : short {
    		Right1	= 1 << 0,
    		Right2	= 1 << 1,
    		Key = 1
    	};
    
    	enum class Group2: short {
    		Right1	= 1 << 0,
    		Right2	= 1 << 1,
    		Key = 2
    	};
    
    	/*
    	So in etwas würde ich es gern wollen
    	template<typename T>
    	bool operator()(T bit)
    	{
    		return ((Access::bits.find(static_cast<int>(T::Key)) != Access::bits.end()) && (Access::bits[static_cast<int>(T::Key)] & bit) == bit);
    	}
    	*/
    	bool operator()(Access::Group1 bit);
    	bool operator()(Access::Group2 bit);
    
    	Access operator=(std::map<int, int> rights)
    	{
    		Access::bits = rights;
    		return *this;
    	}
    } Access;
    
    std::map<int, int> Access::bits;
    
    // Bitvergleich Template
    template<typename T>
    T operator &(int lhs,  T rhs)
    {
    	return static_cast<T>(lhs & static_cast<int>(rhs));
    }
    
    bool Access::operator()(Access::Group1 bit)
    {
    	return ((Access::bits.find(static_cast<int>(Access::Group1::Key)) != Access::bits.end()) && (Access::bits[static_cast<int>(Access::Group1::Key)] & bit) == bit);
    }
    
    bool Access::operator()(Access::Group2 bit)
    {
    	return ((Access::bits.find(static_cast<int>(Access::Group2::Key)) != Access::bits.end()) && (Access::bits[static_cast<int>(Access::Group2::Key)] & bit) == bit);
    }
    
    int main(int argc, char *argv[]) {
    
    	// Diese Daten kommen aus der JSON Datei/Anfrage
    	std::map<int, int> json = {
    		{1, 7}
    	};
    
    	Access = json;
    
    	if (Access(Access::Group1::Right1))
    	{
    		std::cout << "Access Group1::Right1 granted!" << std::endl;
    	}
    
    	if (Access(Access::Group1::Right2))
    	{
    		std::cout << "Access Group1::Right2 granted!" << std::endl;
    	}
    
    	if (Access(Access::Group2::Right1))
    	{
    		std::cout << "Access Group2::Right1 granted!" << std::endl;
    	}
    
    	return 0;
    }
    

    Ich muss nun für jede Gruppe eine Funktion schreiben, welches ich gern mit dem angedeutetem Template umgehen möchte. Das geht aber nicht, weil das "Bitvergleich Template" die anderen Funktionen schon kennen muss. Wie kann ich das Problem lösen. Oder hat jemand eine bessere und schönere Lösung für das Rechtemanagement?

    Wobei ich mich gerade frage warum der Code so unglaublich groß wird nach dem verlassen der main Funktion: https://godbolt.org/g/vkqtHZ
    mfg Spoocy



  • Das klappt doch: Ideone - Code (ich habe die beiden speziellen ()-Operatoren auskommentiert).
    Zum Test, ob die richtigen Groups aufgerufen werden, habe ich 'typeid(T).name' noch zusätzlich ausgeben lassen.

    PS: Den Operator würde ich eher so definieren:

    template<typename T>
    bool operator()(T bit) const
    {
       const auto &it = bits.find(static_cast<int>(T::Key));
       return it != bits.end() ? (it->second & bit) == bit : false;
    }
    


  • Noch eine Frage, den code:

    template<typename T> 
    bool operator()(T bit) const {}
    

    habe ich jetzt ein bisschen abgeändert und in einer anderen Klasse folgendes definiert:

    template<typename T>
    		inline bool granted(T bits)
    		{
    			const auto &it = this->access.find(static_cast<int>(T::Key));
    			return it != this->access.end() ? (it->second & static_cast<int>(bit)) == static_cast<int>(bit) : false;
    		}
    

    Das geht auch. Jedoch laufe ich gefahr das ich irgendwo den aufruf

    this->granted(std::string("")) machen könnte. Also kurz gesagt einen vollkommen falschen Type. Ich weis das es std::enable_if etc gibt. Nur hab ich keine vorstellung wie ich das auf Untertypen von struct Access beschränken kann. Das Struct Access enthält nur noch enum classes!



  • Dann versuchs mal mit static_assert , das müsstest hinbekommen.


Log in to reply