char* länge zur Compile-Zeit ermitteln



  • Hallo.

    Gibt es eine Möglichkeit, dass man die Stringlänge eines char* wärend der Compile-Zeit ermittle bzw. überprüfe?

    folgendes Problem

    // eine Funktion die einen char* String irgendwo einfügt, zusätzlich wird die Länge des String noch mitübergeben, damit diese nicht ermittelt werden muss
    void AddSomething(const char* string, int stringlen);
    
    main()
    {
        std::string str("erster")
    
        AddSomething(str.c_str(), str.size());
        AddSomething("zweiter", 7);
        AddSomething("dritter", 1);    // Problem1
        AddSomething("vierter", 9);    // Problem2
    }
    

    Mir ist klar, dass beim Aufruf AddSomething und Übergabe eines std::string zur Compile-Zeit die Stringlänge nicht ermittelt werden kann, aber ich würde gerne Problem1 und Problem2 zur Compile-Zeit lösen.
    Ist das irgendwie möglich?
    C++11 steht mir leider nicht zur Verfügung, boost kann ich verwenden.

    DANKE!
    LG



  • Wäre es vielleicht eine Möglichkeit, die Stringlänge als Template-Parameter zu übergeben?



  • void AddSomething(std::string str)
    {
        AddSomething(str.c_str(), str.size());
    }
    


  • @daddy_felix
    hmm, bin leider überfragt bzw. verstehe ich den Lösungsansatz nicht, könntest du bitte das genauer schildern

    @Easy Wrap
    ja ist eine Möglichkeit, aber in diesem Fall sollte es auch performant sein und nicht wieder zusätzlich Speicher angelegt werden.



  • http://www.boost.org/libs/utility/doc/html/string_ref.html

    Das strlen wird zwar nicht gezwungenermassen während der Compilezeit ausgewertet, bei höherer Optimierungsstufe üblicherweise aber schon.



  • stringlen schrieb:

    hmm, bin leider überfragt bzw. verstehe ich den Lösungsansatz nicht, könntest du bitte das genauer schildern

    Sowas:

    void AddSomething(const char* s, size_t stringlen)
    {
    	std::cout << s << ": " << stringlen;
    }
    template< size_t N >
    void AddSomething( const char (&s)[N])
    {
    	AddSomething(s, N-1);
    }
    


  • @Jockelx
    Danke! Durch dein Beispiel habe ich folgendes entdeckt:

    template< size_t N >
    constexpr size_t length( char const (&)[N] )
    {
    	return N-1;
    }
    
    int main() {
    
    	static_assert( length("abc") == 3, "string length is not 3" );
    
    	// your code goes here
    	return 0;
    }
    

    Mein Problem ist nun, wie kann ich die C++11 features ersetzen, so das es auch bei mir ohne C++11 läuft?
    static_assert --> BOOST_STATIC_ASSERT_MSG
    nur was mache ich mit constexpr? Da habe ich leider keine Abhilfe gefunden, oder muss ich für eine non-c++11 Umgebung das ganze total anders angehen?



  • static_assert brauchst du sicher nicht (wenns nicht geht, gehts halt nicht) und constexpr doch wahrscheinlich auch nicht, oder?



  • stringlen schrieb:

    @Easy Wrap
    ja ist eine Möglichkeit, aber in diesem Fall sollte es auch performant sein und nicht wieder zusätzlich Speicher angelegt werden.

    Wenn du den Compiler auf einer vernünftigen Optimierungsstufe verwendest hast du einen Performanceunterschied von genau 0.



  • Ich würde es zwar wie du machen (allerdings mit const&), weil Performance wahrscheinlich sowieso nicht auffallen würde, aber dass das genau gleich schnell ist, bezweifel ich.
    Ich kann mir nicht vorstellen, dass der Kompiler auf das erzeugen des Temp-Strings verzichteten kann.
    Allerdings kenn ich mit damit aber auch nicht aus.



  • Das ist alles wahnsinniges Gefrickel und du blähst damit dein Code massiv auf, da für jede Zeichenkette neue Funktionen angelegt werden müssen. Ja, vielleicht wird dieses und jenes rausoptimiert, aber dann compiliert das Ding am Ende zwei Stunden. Super.

    Ein const std::string& str ist hier die richtige Wahl, denn der Overhead ist relativ gering. Durch die Referenz wird auch nichts kopiert und die Länge wird effizient durch std::string berechnet.

    Aber scheint niemanden zu interessieren... Quick and Dirty wäre dies mein Vorschlag:

    #define ADD_SOMETHING(x) AddSomething((x), (sizeof(x) / sizeof(x[0])) - 1)
    // ...
    ADD_SOMETHING("Bla");
    

    Da absolut alles konstant ist, sollte der Compiler hier alles tun können, was möglich ist.

    Bedenke, es geht nur mit Stringliteralen, keine Variablen, nix.



  • jhkhjkhjk schrieb:

    Aber scheint niemanden zu interessieren...

    Du bist der Dritte, der das sagt...


Log in to reply