Probleme bei Tutorial (Programm zur Auflistung aller Primzahlen von 1 bis 100)


  • Mod

    Jetzt kommen wir dem Ziel einer nicht nur absichtlich falsch verstandenen sondern auch absolut unleserlichen Lösung näher. 👍

    P.S.: In C++ natürlich cout.write(...). Den dadurch erzeugten Overhead beim Startup für die Konstruktion des cout-Objektes würde nicht nicht mitzählen.



  • Ich glaub nicht das er noch irgendwas von dem Zeugs versteht, was ihr schreibt :p .



  • Da sein Problem ja schon gelöst wurde, sollte das OK gehen. Behaupte ich mal. Wenn nicht einfach schreien.

    Man könnte jetzt ne TMP Version basteln. Also komplett inklusive Konvertierung ins Dezimalsystem und Konkatenierung der Ergebnisse.

    fwrite(black_template_magic_primes<100>::str, 1, black_template_magic_primes<100>::strlen, stdout);
    


  • hustbaer schrieb:

    Da sein Problem ja schon gelöst wurde, sollte das OK gehen. Behaupte ich mal. Wenn nicht einfach schreien.

    Man könnte jetzt ne TMP Version basteln. Also komplett inklusive Konvertierung ins Dezimalsystem und Konkatenierung der Ergebnisse.

    fwrite(black_template_magic_primes<100>::str, 1, black_template_magic_primes<100>::strlen, stdout);
    

    Mein Unnötigkeitssensor schlägt wieder aus... oha, 6.9 - ich glaube gar, hustbaer sitzt da wirklich dran.



  • Hacker, überleg mal. Wie kann ein Sensor der - sich in deinem Besitz befindend - immer auf Anschlag steht noch weiter ausschlagen? Das kann nicht gehen.

    Und nein, ich sitze da nicht dran.

    Obwohl es auch nicht notwendigerweise "unnötig" wäre, zumindest nicht subjektiv betrachtet. Kann man einiges dabei lernen, bzw. üben wenn es Dinge sind die man schon kann, aber vielleicht länger nicht mehr angewendet hat.



  • hustbaer schrieb:

    Hacker, überleg mal. Wie kann ein Sensor der - sich in deinem Besitz befindend - immer auf Anschlag steht noch weiter ausschlagen? Das kann nicht gehen.

    Ich hab Alufolie rumgewickelt und bediene das ding durch eine Angel und einen Stock, aber der Zeiger zittert immer noch ein bisschen 🤡

    Außerdem mach' ich eigentlich nie unnötige Sachen. Ich bin - in gewissen Zeiten - recht rational.


  • Mod

    hustbaer schrieb:

    Man könnte jetzt ne TMP Version basteln. Also komplett inklusive Konvertierung ins Dezimalsystem und Konkatenierung der Ergebnisse.

    Ei, das ist wirklich übel hart. Da bin ich mir selbst nach einigem Nachdenken nicht sicher, ob das überhaupt geht. Ich glaube man braucht aber mindestens variadic templates. Habe gerade keine Zeit, mir das genauer anzugucken.



  • Variadic Templates waren noch nie erforderlich, sie sind einfach eine Vereinfachung für Typlisten, wie aus dem Alexandrescu bekannt.



  • Kellerautomat schrieb:

    sie sind einfach eine Vereinfachung für Typlisten, wie aus dem Alexandrescu bekannt.

    Das ist Sepp sicherlich bekannt. Aber es sind generische Typlisten 🤡



  • Was soll denn bitte eine generische Typliste sein?



  • Kellerautomat schrieb:

    Was soll denn bitte eine generische Typliste sein?

    Was ich meine ist folgendes: Ich dachte, du meinst, man kann statt

    template<typename ...c>
    void func(//.....
    

    Auch gleich das aufzurufende einsetzen.

    template<char a, size_t s, char b>
    void func(//...
    

    In diesem Fall ist aber (ich weiß nicht ob das Wort hier passt) oberes generischer, nicht?



  • Keine Ahnung, wovon du redest. Das hat damit überhaupt nichts zu tun. Hast du den Alexandrescu überhaupt gelesen? Falls nein -> großer Fehler.



  • SeppJ schrieb:

    Ei, das ist wirklich übel hart. Da bin ich mir selbst nach einigem Nachdenken nicht sicher, ob das überhaupt geht.

    Bitteschön.

    #include <iostream>
    #include <type_traits>
    
    template <bool B>
    struct bool_
    	: std::integral_constant<bool, B>
    {};
    
    template <unsigned I>
    struct unsigned_
    	: std::integral_constant<unsigned, I>
    {};
    
    template <typename A, typename B>
    struct dividable
    	: bool_<A::value % B::value == 0>
    {};
    
    template <typename A, typename B>
    struct or_
    	: bool_<A::value || B::value>
    {};
    
    template <typename I>
    struct increment
    	: unsigned_<I::value + 1>
    {};
    
    template <typename A, typename B>
    struct squared_less_equal
    	: bool_<(A::value * A::value <= B::value)>
    {};
    
    template <typename A>
    struct not_
    	: bool_<!A::value>
    {};
    
    template
    <
    	template <typename, typename> class Func,
    	typename Arg1
    >
    struct bind1st
    {
    	template <typename Arg2>
    	struct binder1st : Func<Arg1, Arg2>
    	{};
    };
    
    template
    <
    	template <typename, typename> class Func,
    	typename Arg2
    >
    struct bind2nd
    {
    	template <typename Arg1>
    	struct binder2nd : Func<Arg1, Arg2>
    	{};
    };
    
    template
    <
    	typename Init,
    	template <typename> class Cond,
    	template <typename> class Next,
    	template <typename> class Do,
    	template <typename, typename> class Combine,
    	typename Else
    >
    struct for_
    	: std::conditional
    	<
    		Cond<Init>::value,
    		typename std::conditional
    		<
    			Cond<Next<Init>>::value,
    			Combine
    			<
    				Do<Init>,
    				for_<Next<Init>, Cond, Next, Do, Combine, Else>
    			>,
    			Do<Init>
    		>::type,
    		Else
    	>::type
    {};
    
    template <unsigned I>
    struct is_prime
    	: not_
    	<
    		for_
    		<
    			unsigned_<2>,
    			bind2nd<squared_less_equal, unsigned_<I>>::template binder2nd,
    			increment,
    			bind1st<dividable, unsigned_<I>>::template binder1st,
    			or_,
    			bool_<true>
    		>
    	>
    {};
    
    template <>
    struct is_prime<2>
    	: bool_<true>
    {};
    
    template <>
    struct is_prime<3>
    	: bool_<true>
    {};
    
    template <char... S>
    struct string : std::identity<string<S...>>
    {
    	static char const c_str[];
    };
    
    template <char... S>
    char const string<S...>::c_str[] = { S..., 0 };
    
    template <typename S1, typename S2>
    struct append
    	: append<typename S1::type, typename S2::type>
    {};
    
    template <char... S1, char... S2>
    struct append<string<S1...>, string<S2...>>
    	: string<S1..., S2...>
    {};
    
    template <unsigned I>
    struct to_string
    	: std::conditional
    	<
    		I < 10,
    		string<I + '0'>,
    		append<to_string<I / 10>, string<I % 10 + '0'>>
    	>::type
    {};
    
    template <typename A, typename B>
    struct less
    	: bool_<(A::value < B::value)>
    {};
    
    template <typename I>
    struct to_string_if_prime
    	: std::conditional
    	<
    		is_prime<I::value>::value,
    		append<to_string<I::value>, string<' '>>,
    		string<>
    	>
    {};
    
    template <unsigned N>
    struct primes_below
    	: for_
    	<
    		unsigned_<0>,
    		bind2nd<less, unsigned_<N>>::template binder2nd,
    		increment,
    		to_string_if_prime,
    		append,
    		string<>
    	>
    {};
    
    int main()
    {
    	std::cout << primes_below<100>::type::c_str << '\n';
    }
    

    http://ideone.com/tswvn

    Man möge mir das überschüssige Whitespace am Ende verzeihen.


  • Mod

    Kellerautomat schrieb:

    http://ideone.com/tswvnMan möge mir das überschüssige Whitespace am Ende verzeihen.

    Sehr schöne Buchlösung, verliert aber Stilpunkte wegen for_ 😉

    Jetzt noch bitte eine Variante, bei der die Tiefe der rekursiven Instantiierung beschränkt ist auf sagen wir 10.



  • Kellerautomat schrieb:

    Keine Ahnung, wovon du redest. Das hat damit überhaupt nichts zu tun. Hast du den Alexandrescu überhaupt gelesen? Falls nein -> großer Fehler.

    Ja, hast Recht. Seh ich mir mal an.



  • Ist std::identity() das neue void main()?

    SCNR 😉



  • Furble Wurble schrieb:

    Ist std::identity() das neue void main()?

    SCNR 😉

    ?????

    Was sagt eigentlich SeppJ dazu? 😉



  • Ich schlage

    #!/usr/bin/make -f
    
    foo: foo.cc
    	$(CXX) $(CXXFLAGS) -o $@ $+
    
    primes.inl:
    	echo \"$(shell primes 1 100)\\n\" > $@
    
    foo.cc: primes.inl
    

    in der Makefile und

    #include <iostream>
    
    int main() {
      std::cout <<
    #include "primes.inl"
        ;
    }
    

    als foo.cc vor.


  • Mod

    Kellerautomat schrieb:

    Was sagt eigentlich SeppJ dazu? 😉

    Zu was genau? Dein Programm? Cool. 👍 Ganz schön viel Mühe. Die Kritik ist doch Pillepalle.

    Jetzt müsstest du aber natürlich eigentlich noch die variadic templates durch klassische Typlisten ersetzen, da du vorher so groß davon geredet hast. 🙂



  • Ich hab' mir das schon überlegt.
    Bis zur Erzeugung des Strings sehe ich kein echtes Problem (hab's nicht implementiert, aber müsste IMO ganz gut gehen -- wenn auch die Compilezeiten sicher massiv ansteigen im Vergleich zur variadic-template Variante).

    Nur mir will einfach keine Möglichkeit einfallen ein grosses char -Array zu erzeugen ohne dabei Overloads für 1 ... N Elemente zu schreiben.
    Und naja... so ein String kann schonmal lange werden. Und ein Klassentemplate mit 1000 spezialisierungen... pfuh. Hardcore 🙂

    Dummerweise kann man ja nicht ein char[N] Array mit einem anderen char[N-1] Array + einem einzelnen char initialisieren, ohne explizit { a[0], a[1] a[2], ... a[N-1], next } zu schreiben.


Anmelden zum Antworten