Variadische Template-Argumente verodern.



  • Hoi,
    ich möchte eine Liste an variadischen Templateargumenten möglichst elegant per || verknüpfen, mit den üblichen C++-Semantiken (Abbruch der Evaluierung sobald 1 Wert wahr etc).

    Das wäre nicht allzuschwer hinzuhacken, aber dafür gibt es doch auch syntaktisch elegante Wege?

    So funktioniert es ja leider nicht, hatte im Kopf dass es in anderem Kontext so ähnlich geht:

    template<class First, class... Rest>
    struct Or
    {
    	template<typename IteratorType>
    	static bool match(IteratorType begin, IteratorType end,
    		IteratorType& newBegin)
    	{
    		bool matched = (First::match(begin, end, newBegin) ||
    			Rest::match(begin, end, newBegin))...;
    		return matched;
    	}
    };
    

    Danke und Grüße,
    Ethon



  • Was soll das Ergebnis einer Oder-Verknuepfung von Typen sein?



  • Jeder der Typen implementiert eine statische match-Funktion, die ein bool zurückgibt. Sieht man doch im Snippet. 🙂



  • variadisch - LMAO. 😃

    Meinst du sowas:

    template<typename IterT,
             typename First>
    bool Or(IterT begin,
            IterT end,
            IterT& newBegin)
    {
            return First::match(begin, end, newBegin);
    }
    
    template<typename IterT,
             typename First,
             typename Second,
             typename ... Rest>
    bool Or(IterT begin,
            IterT end,
            IterT& newBegin)
    {
            if(First::match(begin, end, newBegin) or Second::match(begin, end, newBegin))
                    return true;
    
            return   First::match(begin, end, newBegin)
                  or Or<IterT, Second, Rest...>(begin, end, newBegin);
    }
    

    ?
    Das wäre mein rekursiver Ansatz. Ich kann aber nichts testen, da ich keine Beispiel Typen habe und auch keine Lust habe, sie zu basteln.

    Edit: Jetzt funktionierts.



  • variadisch

    Korrekte Übersetzung, Du Kichererbse. 😉



  • Sowas?

    template<class First, class... Rest>
    struct Or
    {
    	template<typename IteratorType>
    	static bool match(IteratorType begin, IteratorType end,
    		IteratorType& newBegin)
    	{
    		bool matched = (First::match(begin, end, newBegin) ||
    			Or<Rest...>::match(begin, end, newBegin));
    		return matched;
    	}
    };
    
    template<class First>
    struct Or
    {
    	template<typename IteratorType>
    	static bool match(IteratorType begin, IteratorType end,
    		IteratorType& newBegin)
    	{
    		bool matched = (First::match(begin, end, newBegin);
    		return matched;
    	}
    };
    


  • Eisflamme schrieb:

    variadisch

    Korrekte Übersetzung, Du Kichererbse. 😉

    Aha, aber
    http://dict.leo.org/ende?lp=ende&lang=de&searchLoc=0&cmpType=relaxed&sectHdr=on&spellToler=&search=variadic
    http://de.pons.eu/dict/search/results/?q=variadic&l=deen&ie=☠

    Sagen beide, den Begriff variadic gibts nicht...

    Sogar Google erkennt bei variadic die Sprache Spanisch:
    http://translate.google.de/?hl=de&tab=wT#auto/de/variadic

    pumuckl schrieb:

    Sowas?

    template<class First, class... Rest>
    struct Or
    {
    	template<typename IteratorType>
    	static bool match(IteratorType begin, IteratorType end,
    		IteratorType& newBegin)
    	{
    		bool matched = (First::match(begin, end, newBegin) ||
    			Or<Rest...>::match(begin, end, newBegin));
    		return matched;
    	}
    };
    
    template<class First>
    struct Or
    {
    	template<typename IteratorType>
    	static bool match(IteratorType begin, IteratorType end,
    		IteratorType& newBegin)
    	{
    		bool matched = (First::match(begin, end, newBegin);
    		return matched;
    	}
    };
    

    Du redefinierst hier Or , oder?



  • Sone schrieb:

    http://dict.leo.org/ende?lp=ende&lang=de&searchLoc=0&cmpType=relaxed&sectHdr=on&spellToler=&search=variadic
    http://de.pons.eu/dict/search/results/?q=variadic&l=deen&ie=☠

    Sagen beide, den Begriff variadic gibts nicht...

    Sogar Google erkennt bei variadic die Sprache Spanisch:
    http://translate.google.de/?hl=de&tab=wT#auto/de/variadic

    Und weil zwei von vielen Übersetzungsseiten das nicht kennen, bedeutet das, dass es auch keine Übersetzung gibt? Oder dass es garnicht existiert, oder wie? Und Google Übersetzer ist natürlich das Maß der Dinge 🙄

    dict.cc kennts: http://www.dict.cc/?s=variadic

    Sone schrieb:

    Du redefinierst hier Or , oder?

    Ja, war syntaktisch nicht ganz korrekt...

    template <class...> struct Or;
    
    template<class First, class... Rest>
    struct Or<First, Rest...>
    {
        template<typename IteratorType>
        static bool match(IteratorType begin, IteratorType end,
            IteratorType& newBegin)
        {
            bool matched = (First::match(begin, end, newBegin) ||
                Or<Rest...>::match(begin, end, newBegin));
            return matched;
        }
    };
    
    template <class Last>
    struct Or<Last>
    {
       template <class I>
       static bool match(I begin, I end, I& newBegin)
       { return Last::match(begin, end, newBegin); }
    };
    
    struct T { bool match(char*, char*, char*&) {return true;} }
    struct F { bool match(char*, char*, char*&) {return false;} }
    
    #include <iostream>
    int main()
    { 
      char[] hw = "Hello, World!";
      char* const e = hw + sizeof(hw);
      char* ptr = nullptr;
    
      typedef Or<T,T,F> OF1;
      cout << OF1::match(hw, e, ptr) << '\n';
    
      typedef Or<T,T,T> OT1;
      cout << OT1::match(hw,e,ptr) << '\n';
    
      typedef Or<T,T,OT1> OT2;
      cout << OT2::match(hw,e,ptr) << '\n';
    }
    

    Kannn ich auf ideone leider grade nicht testen, da hat der GCC und das Syntax-Highlighting gerade die Grätsche gemacht 😮



  • Ja, das ist schon in Ordnung so, dake. 😉
    Hatte nur eben die Hoffnung, dass es da irgendwo syntaktischen Zucker gäbe, um nicht immer Rekursion implementieren zu müssen.



  • Ethon schrieb:

    Ja, das ist schon in Ordnung so, dake. 😉
    Hatte nur eben die Hoffnung, dass es da irgendwo syntaktischen Zucker gäbe, um nicht immer Rekursion implementieren zu müssen.

    template<typename IterT,
             typename First,
             typename Second,
             typename ... Rest>
    bool Or(IterT begin,
            IterT end,
            IterT& newBegin)
    {
            std::initializer_list<bool> list = {First::match(begin, end, newBegin), Second::match(begin, end, newBegin), Rest::match(begin, end, newBegin)...};
            return std::count(list.begin(), list.end(), true);
    }
    


  • Sorry Hacker. 😉

    mit den üblichen C++-Semantiken (Abbruch der Evaluierung sobald 1 Wert wahr etc).

    So ähnlich ist es mir zunächst auch in den Sinn gekommen.



  • Ethon schrieb:

    Sorry Hacker. 😉

    mit den üblichen C++-Semantiken (Abbruch der Evaluierung sobald 1 Wert wahr etc).

    So ähnlich ist es mir zunächst auch in den Sinn gekommen.

    Stopp! 💡
    ➡ Eigenes count !



  • Also sowas, wie wäre es damit?

    bool one_of(std::initializer_list<bool> const& b)
    {
            for(auto const val : b)
                    if(val)
                            return true;
    
            return false;
    }
    
    template<typename IterT,
             typename First,
             typename Second,
             typename ... Rest>
    bool Or(IterT begin,
            IterT end,
            IterT& newBegin)
    {
            return one_of({First::match(begin, end, newBegin), Second::match(begin, end, newBegin), Rest::match(begin, end, newBegin)...});
    }
    


  • Das verhindert aber nicht, dass du sämtliche Bedingungen evaluierst, sondern nur, dass du dir alle Ergebnisse anguckst.
    Und das gibt es (seit C++11) schon und heißt std::any_of .



  • ipsec schrieb:

    Das verhindert aber nicht, dass du sämtliche Bedingungen evaluierst, sondern nur, dass du dir alle Ergebnisse anguckst.
    Und das gibt es (seit C++11) schon und heißt std::any_of .

    Tja, hab ich beides schon geahnt... 😞

    Tja, neh, dann geht nur die rekursive Variante, hast Recht Ethon.



  • Sone schrieb:

    Eisflamme schrieb:

    variadisch

    Korrekte Übersetzung, Du Kichererbse. 😉

    Aha, aber

    Du zitierst Wörterbücher, die nicht Mal den englischen Begriff kennen, und lachst dann über die Übersetzung?

    http://www.dict.cc/?s=variadic



  • edit: zu spät...



  • Eisflamme schrieb:

    Sone schrieb:

    Eisflamme schrieb:

    variadisch

    Korrekte Übersetzung, Du Kichererbse. 😉

    Aha, aber

    Du zitierst Wörterbücher, die nicht Mal den englischen Begriff kennen, und lachst dann über die Übersetzung?

    http://www.dict.cc/?s=variadic

    Nein, eigentlich wollte ich damit andeuten dass das alles eine sinnlose Diskussion wird, weil es den begriff variadic gar nicht gibt... anscheinend gibt es ihn doch...

    Wie auch immer: variadisch fand' ich einfach nur lustig, nicht falsch o. ä.



  • Sone schrieb:

    Nein, eigentlich wollte ich damit andeuten dass das alles eine sinnlose Diskussion wird, weil es den begriff variadic gar nicht gibt...

    Selbst wenn er in keiner Übersetzungsseite aufgetaucht wäre, ist er im Standard fest definiert, jeder hier weiß, was gemeint ist (auch mit der deutschen Übersetzung), und das einzig sinnlose ist, dass du ne Diskussion darüber vom Zaun gebrochen hast 😛

    PS, wozu oben überhaupt initializer_list?

    template <unsigned N>
    constexpr bool any_of(const bool* arr)
    {
      return (N == 0) ? false : 
               ((N==1) ? (*arr): (any_of<N/2>(arr) || any_of<N-N/2>(arr+N/2)));
    }
    
    template<class... Rest>
    struct Or
    {
        template<typename IteratorType>
        static bool match(IteratorType begin, IteratorType end,
            IteratorType& newBegin)
        {
            const bool matched[] = {Rest::match(begin, end, newBegin)...};
            return any_of<sizeof...(Rest)>(matched);
        }
    };
    
    struct T { static constexpr bool match(char*, char*, char*&) {return true;} };
    struct F { static bool match(char*, char*, char*&) {return false;} };
    
    #include <iostream>
    using namespace std;
    int main()
    { 
      char hw[] = "Hello, World!";
      char* const e = hw + sizeof(hw);
      char* ptr = 0;
    
      typedef Or<F,F,T> OT1;
      cout << OT1::match(hw, e, ptr) << '\n';
    
      typedef Or<F,F,F> OF1;
      cout << OF1::match(hw,e,ptr) << '\n';
    
      typedef Or<F,F,OF1> OF2;
      cout << OF2::match(hw,e,ptr) << '\n';
    
      cout << Or<>::match(hw,e,ptr) << '\n';
    }
    

  • Mod

    Hier eine nicht-rekursive Variante

    template<class... Rest>
    struct Or
    {
        template<typename IteratorType>
        static bool match(IteratorType begin, IteratorType end,
            IteratorType& newBegin)
        {
            bool result = false;
            const bool matched[] = { result = result || Rest::match(begin, end, newBegin)...};
            return (void)matched, result;
        }
    };
    
    struct T { static constexpr bool match(char*, char*, char*&) {return true;} };
    struct F { static bool match(char*, char*, char*&) {return false;} };
    
    #include <iostream>
    using namespace std;
    int main()
    {
      char hw[] = "Hello, World!";
      char* const e = hw + sizeof(hw);
      char* ptr = 0;
    
      typedef Or<F,F,T> OT1;
      cout << OT1::match(hw, e, ptr) << '\n';
    
      typedef Or<F,F,F> OF1;
      cout << OF1::match(hw,e,ptr) << '\n';
    
      typedef Or<F,F,OF1> OF2;
      cout << OF2::match(hw,e,ptr) << '\n';
    
      cout << Or<>::match(hw,e,ptr) << '\n';
    }
    

Log in to reply