Wie Klassen-Template Objekte in einem Array nutzen (non Template, constexpr, inline)

#6714558
Lesenswert?

Fortsetzung aus diesem Thread.
Beitrag "Re: Buchempfehlung C++ und MCUs"

Hallo,

@ Wilhelm:
Ich habe jede Frage beantwortet. Dein Vorwurf ist vollkommen 
fehlplatziert. So kommen wir jedenfalls nicht weiter.
Wenn inline so einfach ist, dann zeige es mir bitte.
Der komplette Code steht hier.
Beitrag "Re: Buchempfehlung C++ und MCUs"


@ Oliver:
Eine Funktion ohne Rückgabewert ist sinnlos diese constexpr zu machen.
Ist das die richtige Antwort?

Dann habe ich das mit Inline verwechselt. Inline fügt nur den Code an 
Ort und Stelle ein um Sprünge zu vermeiden.
Constexpr rechnet etwas aus und fügt das Ergebnis des konstanten 
Ausdrucks an Ort und Stelle ein. Korrekt?
Nur beim experimentieren fiel mir auf das inline deklarierte Methoden 
die Wirkung von kleineren Code hatten. Also wirkte inline für mich wie 
constexpr. Theoretisch müßte der Code mit inline größer werden wenn 
gleicher Code mehrfach irgendwo steht statt nur eine Sprungmarke zur 
Methode.

Wenn inline kein Problem ist, dann würde ich dich bitten mir zu zeigen 
wie man es richtig macht.
Der komplette Code steht hier.
Beitrag "Re: Buchempfehlung C++ und MCUs"


@ M.K.B.
Damit bist du auf der gleichen Welle wie Wilhelm? Denkt wirklich jemand 
das ich mir fehlende Standardlibs nachbauen kann wenn ich hieran 
scheitere? Dann baue ich mir mehr Probleme ein als was ich damit lösen 
würde. Das macht keinen Sinn.


@ Klaus W.
Siehe Anhänge. Standardbenutzung wäre
1
#include <NanoEveryPin.h>
2

3
OutputPin <13> led13;
4

5
void setup(void) 
6
{
7
  led13.init();
8
}
9

10
void loop(void) 
11
{
12
  led13.toggle();
13
}
Angehängte Dateien:
Beitrag #6714575 wurde von einem Moderator gelöscht.
#6714641
Lesenswert?

Veit D. schrieb:
> Fortsetzung aus diesem Thread.
> Beitrag "Re: Buchempfehlung C++ und MCUs"
>
> Hallo,
>
> @ Wilhelm:
> Ich habe jede Frage beantwortet. Dein Vorwurf ist vollkommen
> fehlplatziert.

Ich werfe Dir gar nichts vor. Es ist Deine Sache, ob Du Dich mit 
Thematiken im Detail befasst, nachliest und verstehst oder nicht.

> So kommen wir jedenfalls nicht weiter.
> Wenn inline so einfach ist, dann zeige es mir bitte.
> Der komplette Code steht hier.
> Beitrag "Re: Buchempfehlung C++ und MCUs"

Wahrscheinlich denkst Du immer noch, inline sei dazu da, einen 
Funktionsaufruf wegzuoptimieren. Das ist falsch. Dazu müsste man aber 
wirklich auch nur einmal konkret googlen. Ein Funktionsinlining wie Du 
es meinst machen die Compiler heute eh schon sofern möglich. Optimierung 
ist Compilers Aufgabe.

Inline hat heute die Bedeutung, eine Verletzung der ODR auszuschließen.

> Dann habe ich das mit Inline verwechselt. Inline fügt nur den Code an
> Ort und Stelle ein um Sprünge zu vermeiden.

Nein. s.o.

> Constexpr rechnet etwas aus und fügt das Ergebnis des konstanten
> Ausdrucks an Ort und Stelle ein. Korrekt?

Nur, wenn das möglich ist. Du kannst eine Funktion constexpr 
deklarieren, sie ist es aber nicht, und wird dann auch nicht so vom 
Compiler behandelst (NDR!).

consteval (immediate function) erzwingt das.

> Nur beim experimentieren fiel mir auf das inline deklarierte Methoden

Methoden gibt es nicht in C++: Funktionen, entweder Elementfunktionen 
oder freie Funktionen.

> die Wirkung von kleineren Code hatten. Also wirkte inline für mich wie
> constexpr.

In Deinem Sinne hat inline und constexpr nichts miteinander zu tun. Wohl 
aber impliziert constexpr inline bei Variablen.

Schau doch einfach mal in cppreference!

> Theoretisch müßte der Code mit inline größer werden wenn
> gleicher Code mehrfach irgendwo steht statt nur eine Sprungmarke zur
> Methode.

Nein, s.o.

> @ M.K.B.
> Damit bist du auf der gleichen Welle wie Wilhelm? Denkt wirklich jemand
> das ich mir fehlende Standardlibs nachbauen kann wenn ich hieran
> scheitere?

Es gibt nicht C++-Standard-Libs, sondern nur eine 
(Schnittstellen-Beschreibung).

Wenn Du natürlich schon an std::array scheiterst ist das tragisch. Oder 
den mundgerechten Code von fromscratch zu kopieren. Mehr kann man Dir 
eigentlich nicht geben.

Nachfolgend nochmal eine Variante zu denen, die ich Dir schonmal gegeben 
hatte. Ich hatte Dir schon

A) std::array mit Laufzeitinterface
B) std::array mit std::variant für Zeiger (ohne Laufzeitpolymorphie)
C) std::array mit std::variant für Instanzen (ohne Laufzeitpolymorphie)

gezeigt. Ok, wegen std::array war das alles nichts für Dich.

Anbei noch eine Variante, in der die Hardware als templates modelliert 
sind. Warum man das so machen sollte, hatte ich auch schon begründet.

Damit degradieren die Hardware-Abstraktionen zu Typen (also Instanzen 
von templates, keine Objekte).
Für den Code brauchst Du keine zusätzlichen Komponenten außer std::byte. 
Falls Du das auch nicht herstellen oder ergooglen kannst, ändere es auf 
std::uint8_t.

Das Beispiel habe ich analog zu den vorgenannten gestaltet, um es 
Vergleichbar zu machen. Hierin sind

P1, P2 die Register-Maps hypothetischer MCU-Peripheriekategorien (Port, 
Uart, ...).

Per ist die softwaretechnische Modellierung der Komponenten. Diese wird 
instanziiert mit der Nummer und Registersatz. Das es zwei Registersätze 
gibt, liegt an den ursprünglichen Beispielen. In der Praxis kommt das 
selten, aber auch vor (kleiner Uart, großer Uart).

Da keine Objekte instanziiert werden, gibt es keine ctor-Aufrufe, 
sondern es erfolgt ein init().

Das bisschen Meta-Programmierung käme in eine eigene Bib zur 
Manipulation von Typ-Containern.

Wie zu erwarten, ergibt dieses Beispiel den kompaktesten Code (D).

In Bytes für avr4809:

A: 434
B: 297
C: 330
D: 248

(P.S.: alles kurz auf dem Weg zur Arbeit runtergetippt. Compiliert, kann 
aber Fehler enthalten ...)
1
#include <utility>
2

3
struct MCU {
4
    struct P1 {
5
        static inline volatile std::byte r1;
6
        static inline volatile std::byte r2;
7
    };
8
    struct P2 {
9
        static inline volatile std::byte r1;
10
        static inline volatile std::byte r2;
11
    };
12
};
13

14
template<auto N, typename P>
15
struct Per final {
16
    static void init(const std::byte v){
17
        value = v;
18
    }
19
    static std::byte get(){
20
        return value;
21
    }
22
    static void set(const std::byte v) {
23
        P::r1 = v;
24
    }
25
    static void toggle(const std::byte v) {
26
        P::r1 |= v;
27
    }
28
    static void store() {
29
        value = P::r2;
30
    }
31
    static inline std::byte value{};
32
};
33

34
template<typename... TT> struct List {};
35

36
template<typename> struct Visit;
37
template<typename... II>
38
struct Visit<List<II...>> {
39
    static void all(const auto& c) {
40
        (c(II{}),...);
41
    }
42
};
43

44
namespace detail {
45
    template<typename L> struct front_impl;
46
    
47
    template<typename F, typename... II>
48
    struct front_impl<List<F, II...>> {
49
        using type = F;
50
    };
51
}
52

53
template<typename L>
54
using front = detail::front_impl<L>::type;
55

56
int main() {
57
    using a = Per<0, MCU::P1>;
58
    using b = Per<0, MCU::P2>;
59
    using c = Per<1, MCU::P1>;
60
    using d = Per<1, MCU::P2>;
61
    
62
    using list = List<a, b, c, d>;
63

64
    a::init(32_B);
65
    b::init(42_B);
66
    c::init(52_B);
67
    d::init(62_B);
68
    
69
    while(true) {
70
        std::byte x{};
71
        
72
        Visit<list>::all([&]<typename C>(C){
73
                             C::store();
74
                             x |= C::get();
75
                    });
76
        
77
        front<list>::set(x);
78
    }
79
}
#6714911
Lesenswert?

Wilhelm M. schrieb:
> Wenn Du natürlich schon an std::array scheiterst ist das tragisch.

Beim rumgooglen in Zusammnehang mit diesem Thema hier bin ich über das 
hier gestolpert:

https://github.com/modm-io/avr-libstdcpp

Ist zwar nicht vollständig, aber all das, was man für das Thema hier 
braucht, ist drin. Array, tuple, type traits, usw. Das eröffnet einen 
Haufen neue Möglichkeiten ;)

Oliver
#6715085
Lesenswert?

Hallo,

das ist eine andere Vorgehensweise/Programmierart wie ich aktuell 
gewohnt bin bzw. gemacht habe. Mit variadic templates hatte ich nur kurz 
rumgemacht. Ich hoffe jetzt das ich damit etwas anfangen kann. Das wird 
seine Zeit brauchen. Ich bedanke mich Wilhelm.

Laut meinem Buch werden die Begriffe Elementfunktion (member functions) 
und Methode synonym verwendet. So ganz falsch kann es demnach nicht 
sein.  ;-)  Die Umgewöhnung wäre mein geringstes Problem.

Vorläufig wohl letzte Frage. Welchen Vorteil hätte denn std::byte statt 
uint8_t ? Sind doch beide 8Bit breit.
#6715115
Lesenswert?

Veit D. schrieb:
> Laut meinem Buch werden die Begriffe Elementfunktion (member functions)
> und Methode synonym verwendet.

Ein Buch über C++? Sehr merkwürdig?

Veit D. schrieb:
> Vorläufig wohl letzte Frage. Welchen Vorteil hätte denn std::byte statt
> uint8_t ?

Die Semantik: ein uint8_t ist eine vorzeichenlose Ganzzahl. Ein 
std::byte ist eine Sammlung von 8-Bit. Für uint8_t ist bspw. der op-+ 
definiert, weil das Sinn macht. Für den DT std::byte nicht, weil es 
keinen Sinn macht. Wohl aber für std::byte die Bit-Operationen, diese 
machen strenggenommen für uint8_t wieder (wenig) Sinn. Deswegen findest 
Du auch häufig etwa Char oder char_t, etc. statt char. Dann bedeutet 
Char tatsächlich ein Zeichen, und damit zu rechnen ist schlicht 
Blödsinn.
Spruch: eingebaute (primitive) DT sind eigentlich nur dazu da, dass man 
sie nicht benutzt. Man versucht möglich, domänespezifische DT zu bilden. 
Das ist ja eine der großen Stärken von C++, dass das kostenneutral 
möglich ist.
Ebenso etwa für physikalische Einheiten: statt double eben Kilometer mit 
den entsprechenden UDL-Ops dazu.

Veit D. schrieb:
> Mit variadic templates hatte ich nur kurz
> rumgemacht.

Soso, damit rumgemacht ...

Variadic templates sind der moderne Schlüssel zu (modernen) 
Meta-Funktionen. Die Meta-Funktion front<> etwa, zeigt Dir wie es geht. 
Kleiner Tipp: versuche dazu eine Meta-Funktion back<> zu schreiben.
#6715203
Lesenswert?

Hallo,

"Kurz rumgemacht" bedeutet, ich habe mit dem Bsp. aus dem Buch versucht 
das nachzuvollziehen und etwas abgeändert. Mehr nicht. Der Syntax wird 
sehr schnell sehr kompliziert. Deswegen hatte ich das abgebrochen.

Mein Buch ist "Der C++ Programmierer" von Ulrich Breymann. Stand C++ 17. 
Auch außerhalb des Buches habe ich sehr oft den Begriff Methode gelesen. 
Weshalb das für mich eher geläufig ist. Seitdem habe ich mir gemerkt das 
Variablen in Klassen Member und Funktion in Klassen Methoden genannt 
werden. Aber das soll jetzt bitte keine Baustelle werden. Das ist mir 
aktuell vollkommen egal.

std::byte. Verstehe soweit. Notgedrungen muss ich jedoch uint8_t 
verwenden. Wenn ich std::byte gegen uint8_t tausche und das '_B' bei den 
4 inits wegnehme kompiliert es bei mir.

Mit front meinst du einen Wert übergeben und mit back sich einen 
Rückgabewert  abholen?
#6715334
Lesenswert?

Veit D. schrieb:
> Hallo,
> Mein Buch ist "Der C++ Programmierer" von Ulrich Breymann. Stand C++ 17.

Dann sage bitte die Auflage und die Seite, wo das vorkommt.

> Auch außerhalb des Buches habe ich sehr oft den Begriff Methode gelesen.

Ja, beim googlen findet man viel Mist.

> Weshalb das für mich eher geläufig ist. Seitdem habe ich mir gemerkt das
> Variablen in Klassen Member und Funktion in Klassen Methoden genannt
> werden. Aber das soll jetzt bitte keine Baustelle werden. Das ist mir
> aktuell vollkommen egal.

Die richtigen Begriffe zu verwenden, ist schon wichtig und hilft bei der 
Kommunikation. Wenn der eine Arzt dem anderen sagt, er solle die Milz 
entfernen, meint aber eigentlich den Blinddarm, so ist das schon 
ärgerlich.

> std::byte. Verstehe soweit. Notgedrungen muss ich jedoch uint8_t
> verwenden. Wenn ich std::byte gegen uint8_t tausche und das '_B' bei den
> 4 inits wegnehme kompiliert es bei mir.

Du hast schon eine komische Art der Wissensaneignung: ich habe dir 
mindestens zweimal den Hinweis auf fromscratch, also die 
cppstdlib-Implementierung auf einfache Art von A. O'Dwyer gegeben. 
Offensichtlcih hälst Du es gar nicht für nötig, Dir das mal anzusehen. 
Die GNU stdcpplib-Impelementierung ist übrigens auch OSS, und die Header 
hast Du sogar auch Deiner Maschine. Dann gab es von Oliver S. den 
Hinweis auf eine avr-cppstdlib. Auch da hast Du nicht hineingeschaut.
Hättest Du mal gegoogelt zusammen mit meinem Hinweis hier drüber, dass 
std::byte etwas mit scoped enums zu tun haben könnte, hat Dich nicht 
bewogen, mal nach zu sehen.

Also ich muss sagen, das ist schon Missachtung der Helfenden.

Hier ist es:
1
    enum class byte : uint8_t {};

Und das 0x00_B?
Auch hier hilft mal im Breymann zu lesen oder cppreference anzusehen: 
das _B ist ein user-defined-literal-Operator.

Ok, der ist nicht Standard, sorry. Hatte ich in meinem Beispiel 
übersehen, aber ich verwende meine eigene, sehr auf µC angepasste 
Version einer eigenen cppstdlib. Dort habe ich diesen UDL-Op eingebaut, 
weil es praktisch ist.

> Mit front meinst du einen Wert übergeben und mit back sich einen
> Rückgabewert  abholen?

Was macht front() bzw. back() bei einem std-Container?
Genau, liefert die entsprechenden Werte, wenn vorhanden. Also front() 
eine Ref auf das erste Element, und back() eine ref auf das letzte 
Element dieses Containers.

So, nun haben wir aber keine Funktion, sondern wohl ein Klassentemplate. 
Diese Art der templates nennt man Meta-Funktionen. Für diesen besonderen 
Namen gibt es die Gründe:

- in C++ gibt es keine vorgegebene Syntax dafür,
- sie manifestieren sich nicht in Maschinencode,
- sie können alle vier Arten von Abbildungen, also

-- Wert -> Wert,

-- Wert -> Typ,

-- Typ -> Wert,

-- Typ -> Typ,

realisieren.

Die Art, wie ich sie hingeschrieben habe über die partielle 
Spezialisierung eines Klassentemplates ist gewissermaßen der Klassiker 
unter den Schreibweisen. Aber auch das kann man sich alles ergooglen ;-)

List<> ist übrigens ein Typ-Container. Also, ein Container, der 
Datentypen beinhaltet, keine Werte!

Datentypen existieren nur in der Hochsprache wie C++, im Maschinencode 
gibt es keine Datentypen, nur Werte. Also ist es klar, das dieser 
Typ-Container gar keinen Niederschlag im Maschinencode findet. Alles nur 
Compilezeit.

Um über solche Container zu iterieren (zur Compilezeit) benutzt man 
gerne das Visitor-Pattern - in diesem Fall also auch als Meta-Funktion. 
Weil es keine vorgegebene Form von Meta-Funktione in C++ gibt, gibt es 
auch keine eingebaute Form der Iteratoion über eine Typ-Liste.
Falls Du nicht weisst, was das Visitor-Pattern bei Wertcontainern als 
Laufzeitpattern macht, dann schaue es bitte nach!

Visit<> ist nun wieder eine Meta-Funktion, die über alle Typen des 
Typ-Containers List<...> iteriert, und dabei für jeden Typ das Callable, 
in diesem Fall das Closure, dass durch die generische lambda-expression 
erzeugt wird, aufruft.
Der eigentliche Kern dieser Iteration ist der Faltungsausdruck über den 
Komma-Operator:
1
     (c(II{}),...);

Diese recht simple und elegante Form mit dem Faltungsausdruck setzt 
voraus, dass die Typen des Parameterpacks II tatsächlich instanziierbar 
sind, obwohl die Instanzen nie benutzt werden, und der Compiler das 
daher tatsächlich nie materialisiert (der Parameter in der lambda-expr. 
hat noch nicht einmal einen Namen).
Man kann (und hat früher) die Iteration in Metafunktionen oft als 
Rekursion geschrieben, aber das erspare ich Dir. (Wobei Du das brauchst, 
wenn Du wie oben vorgeschlagen zur Metafunktion front<> auch mal back<> 
schreibst als kleine Übung).
#6715349
Lesenswert?

Wilhelm M. schrieb:
> Man kann (und hat früher) die Iteration in Metafunktionen oft als
> Rekursion geschrieben, aber das erspare ich Dir. (Wobei Du das brauchst,
> wenn Du wie oben vorgeschlagen zur Metafunktion front<> auch mal back<>
> schreibst als kleine Übung).

back<> könnte rekursiv implementiert werden, in diesem Fall hier ginge 
es aber auch ohne. Trotzdem ist die rekursive Implementierung ein gute 
Übung um sich mit Templates vertraut zu machen.
1
template<typename... II>
2
struct back_impl<List<II...>> {
3
    using type = decltype((II{}, ...));
4
};
#6715368
Lesenswert?

M.K. B. schrieb:
> back<> könnte rekursiv implementiert werden, in diesem Fall hier ginge
> es aber auch ohne.

Ja, und das ich auch sehr gut, weil es zur Compilezeit schneller ist. 
Denn die rekursive Template-Instanziierung kann recht teuer werden. Der 
Komma-Operator erlebt in diesem Zusammenhang eine nie erwartete 
Renaissance ;-)

Trotzdem finde ich die rekursive eine sinnvolle Variante zur 
Einarbeitung in das Thema, wie Du und ich schon betont haben.
#6715431
Lesenswert?

Hallo Wilhelm,

bei dir benötigt man auch Nerven wie Stahlseile. Alles was einem vor die 
Füße gewurfen wird muss man umgehend gelesen, verstanden und 100% 
verinnerlicht haben. Selbst wenn man keine Frage gestellt hat wird volle 
Breitseite geschossen. Als wenn man den ganzen Tag nichts anderes zu tun 
hätte. Komm mal wieder runter! Was an dem _B hier praktisch ist kann ich 
nicht erkennen. Maximale Verwirrung. In dem Bsp. laut meiner Meinung 
überflüssig.

Wenn man sein Gegenüber fordert ist das ja okay. Wenn man sein Gegenüber 
überfordert endet es in Frust. Aktuell stehe ich dazwischen.

Ich konnte nicht erahnen wo die Reise hingeht. Ich muss erstmal das Buch 
weiterlesen und verstehen, dann deinen/euren Code verstehen usw..

Übrigens gibts die C++17 Ausgabe des Buches nur in der 5. Auflage. 
Methode: Seite 160 und 31/32 und 968.

**Danke an alle.**
#6715438
Lesenswert?

Veit D. schrieb:
> Alles was einem vor die
> Füße gewurfen wird muss man umgehend gelesen, verstanden und 100%
> verinnerlicht haben.

Du kannst Dir ruhig Zeit lassen ;-)

Veit D. schrieb:
> Selbst wenn man keine Frage gestellt hat wird volle
> Breitseite geschossen.

Du bist doch hier in diesem speziellen Forum, da ist das so üblich.

Veit D. schrieb:
> Komm mal wieder runter!

Ich bin absolut tiefentspannt.

Veit D. schrieb:
> Was an dem _B hier praktisch ist kann ich
> nicht erkennen. Maximale Verwirrung.

Ok, dann mach das Beispiel mit std::byte und ohne den UDL-Op _B.

Veit D. schrieb:
> In dem Bsp. laut meiner Meinung
> überflüssig.

Ja, das ist der Punkt bei Dir. Du hast sehr schnell eine Meinung, ohne 
das Du je in der Lage warst, dass umzusetzen oder in einen anderen 
Kontext einzubauen.

Veit D. schrieb:
> Übrigens gibts die C++17 Ausgabe des Buches nur in der 5. Auflage.
> Methode: Seite 160 und 31/32 und 968.

Ok, das werde ich zu Hause mal nachsehen ... mal sehen, was er damit 
sagen wollte.
#6715706
Lesenswert?

Veit D. schrieb:
> Hallo,
>
> egal ob ich cstddef inkludiere oder
> enum class byte : uint8_t {};
> selbst definiere, es kompiliert nicht.

Ja, das habe ich genau so erwartet. Das war auch Sinn meiner Bemerkung, 
Du solltest es mal ohne den UDL-Op versuchen.
Ich hatte Dir auch gesagt, dass ich diesen UDL-Op in meiner angepassten 
Realisierung der cppstdlib zusätzlich hinzugefügt habe. Daher kann er ja 
wohl schlecht in Deiner lokalen <cstddef> enthalten sein.


Allerdings hast Du oben recht deutlich erklärt, dass die Schreibweise 
_B, also der UDL-Operator, maximale Verwirrung sei und Deiner Meinung 
nach vollkommen unnötig.

Und es ist mal wieder wie immer: anstatt mal in Ruhe - es hat Dich 
niemand gezwungen, so schnell eine Antwort zu schreiben - nach zu lesen, 
kommt wieder einfach nur: geht nicht. Wenn Du nicht wirklich an Deiner 
Lernstrategie etwas änderst und Eigeninitiative walten lässt, dann wird 
das nie was.

> Die inits gefallen dem Compiler nicht.
> error: cannot convert 'int to 'byte'

Prima, Du hast schon mal die Fehlermeldung gelesen. Hast Du sie auch 
verstanden?

Der user-defined-literal-operator, den Du für völlig unnötig hälst, 
hatte offensichtlich ja schon einen Zweck.

Was kann man ohne den UDL-Op machen, wenn ein Konversionsproblem 
auftritt? Genau, eine explizite Typumwandlung erzwingen ;-)
1
    std::byte x = static_cast<std::byte>(42);

Das schreibt natürlich niemand hin.

Schonmal was von automatischer Typinferenz gehört? Falls nicht, bitte 
nachlesen:
1
auto x = std::byte{42}.

Achtung: was ist das auf der rechten Seite? Ja, ein ctor.
Jetzt ist natürlich die Frage, wie Du das bei dem init(...) in meinem 
Code oben nutzen kannst.

Wie wäre es mit:
1
    a::init(std::byte{42});

Das ist zwar gut zu lesen, weil explizit, aber doch noch etwas länglich. 
Und jetzt sind wir bei dem UDL-Operator. Aber da schlage ich vor, dass 
Du jetzt wirklich mal Deinen Breymann hernimmst und das nachliest. Oder 
halt in cppreference (kennt Du das?).

So, Kaffee ist fertig ...
#6715847
Lesenswert?

Veit D. schrieb:
> Die inits gefallen dem Compiler nicht.
> error: cannot convert 'int to 'byte'

Du solltest dich wirklich mal daran gewöhnen, als allererstes in solch 
einem Fall „std::byte“ in die google-Suchleiste zu tippen, und dann die 
Doku dazu zu lesen.

C++ per trial and error funktioniert einfach nicht, und nichts seit 
C++11 in der Sprache ist selbsterklärend.

Wenn du da wirklich einsteigen willst, bedeutet das einen Haufen Arbeit. 
Zudem würde ich da doch den Umweg über den PC und eine vollwertige 
standardlib empfehlen. Der Weg zurück auf den AVR ist nicht so schwer.

Oliver
#6716015
Lesenswert?

Hallo,

jetzt verstehe ich nichts mehr. Zuerst sollte ich std::byte ohne _B 
verwenden, was wie festgestellt nicht funktioniert. Danach stellt sich 
heraus das es nicht funktionieren kann, weil du das bei dir anders 
gelöst hast und man dafür einen UDL-Operator benötigt. Wer soll dabei 
noch durchblicken? Demnach wurde ich an der Nase herumgeführt?

Ich hatte mir gestern cstddef angeschaut und noch folgendes probiert, 
was die gleiche Fehlermeldung brachte.
1
a::init( static_cast<std::byte>(32) );

Womit ich nicht klar komme ist wie das mit dem enum überhaupt 
funktioniert. enum ist ein Aufzählungstyp. Wie kann man dem einen Wert 
zuweisen welchen der Typ gar nicht kennt?

Ich habe mir die aktuelle Version von Code Blocks installiert und mingw 
Toolchain 10.3. auf den PC geholt. Die Beschreibung gibts ja 
glücklicherweise von U.Breymann zum aktuellen Buch online.

Ich hatte es bisher umgekehrt gehalten. Probiere es erst gar nicht auf 
dem PC, dann wird man nicht verleitet Dinge zu nutzen die man auf dem 
AVR gar nicht hat.  :-)

Die Vorwürfe nerven mich. Wenn ich nicht nachgeschaut hätte und nicht 
Google benutzt hätte wäre ich ja wohl kaum vom irreführenden 'utility' 
(worin std::byte nicht definiert ist) auf 'cstddef' gekommen. Also gar 
so blöd kann ich nicht sein. Und wenn ich zu doof wäre, wäre ich wohl 
kaum auf die Ausweichmöglichkeit uint8_t gekommen wenn std::byte nicht 
geht.
#6716034
Lesenswert?

Veit D. schrieb:
> Also gar
> so blöd kann ich nicht sein.

Ich habe nicht gesagt, dass Du blöd bist!

Ich habe gesagt, dass Deine Lernstrategie verbesserungswürdig scheint in 
meinen Augen.

Veit D. schrieb:
> Die Vorwürfe nerven mich.

Vorwürfe sehen anders aus. Es ist Kritik an Deiner Herangehensweise.
Mich nervt auch einiges.

Veit D. schrieb:
> Ich hatte mir gestern cstddef angeschaut und noch folgendes probiert,
> was die gleiche Fehlermeldung brachte.
> a::init( static_cast<std::byte>(32) );

Das kann nicht sein. Bitte zeige die Fehlermeldung.

Veit D. schrieb:
> Zuerst sollte ich std::byte ohne _B
> verwenden, was wie festgestellt nicht funktioniert.

Falsch. Du hast gesagt, das sei maximal verwirrend, und DU hälst das für 
unnötig! Um Dich darauf zu stoßen, dass das eben nicht völlig unnötig 
ist, habe ich es Dich ausprobieren lassen. Denn ich war mir ziemlich 
sicher, dass ein einfacher Hinweis nicht gefruchtet hätte bzw. Du ihn 
einfach mal so überlesen hättest bzw. für vollkommen unnötig hälst.

Veit D. schrieb:
> Ich hatte es bisher umgekehrt gehalten. Probiere es erst gar nicht auf
> dem PC, dann wird man nicht verleitet Dinge zu nutzen die man auf dem
> AVR gar nicht hat.  :

Auch das sage ich gebetsmühlenartig (vllt nicht nicht in diesem jungen 
Thread): C++ / C lernt man nicht auf einem µC!
Denn C++ ist keine objektorientierte Sprache: C++ ist eine 
Multiparadigmen-Sprache: man kann prozedural, objektorientiert, 
generisch und funktional programmieren und alles zusammen mischen. Der 
Vorteil ergibt sich je nach Problemstellung aus der Kombination der 
Paradigmen. Es anschließend kann man sich auf ein µC "wagen". Und selbst 
auf dem PC ist es von grundlegender Bedeutung, dass man versteht, auf 
welchen Ebenen man sich bewegt: bespielsweise ist die template-Mechanik 
eine turing-vollständige Sprache in der Sprache. Und man sollte sich 
klar machen, dass man "Berechnungen" über das Typsystem machen kann, man 
hat also ein algebraisches System damit (und concepts machen es zudem 
noch komfortabel).

Oliver S. schrieb:
> C++ per trial and error funktioniert einfach nicht, und nichts seit
> C++11 in der Sprache ist selbsterklärend.

Daher kann ich das nur unterstützen.
Man sollte sich schon mal ein paar Gedanken über DT und Werte, 
funktionale Abbildungen, ADT, etc... machen.
#6716037
Lesenswert?

Ich würde dir gerne helfen, habe aber keine Lust mir deine Beschwerden 
durchzulesen.

Schreibe doch bitte einfach, was bei dir nicht geht und warum du denkst, 
dass es gehen müsste. Damit kann man dir gut Helfen, weil man versteht 
wo du etwas anders verstanden hast.
Die Antwort kann auch ruhig erst in ein paar Tagen kommen, wenn du Zeit 
hattest es in Ruhe auszuprobieren.
#6716158
Lesenswert?

> Veit D. schrieb:
>> Ich hatte mir gestern cstddef angeschaut und noch folgendes probiert,
>> was die gleiche Fehlermeldung brachte.
>> a::init( static_cast<std::byte>(32) );
>
> Das kann nicht sein. Bitte zeige die Fehlermeldung.

Ich sollte langsamer machen. Die Fehlermeldung bezieht sich auf das 
Nächste init. Sorry, mein Fehler. Habs soeben nochmal probiert.

Ich leg das erstmal beiseite und gehe Luft holen ...
#6716356
Lesenswert?

Zu den Methoden bzw. Elementfunktionen:
Das ist nicht einheitlich, deshalb würde ich es nicht zu einer Religion 
ausarten lassen.

Es gibt die Meinung, daß es in C++ nicht Methoden heißen darf. 
Allerdings ist C++ jetzt auch nicht die einzige Sprache in der OO-Welt, 
und wer in mehreren Ecken unterwegs ist, sieht das entspannter.

Ich glaube nicht, daß es lohnt, darüber lange zu streiten.
#6716364
Lesenswert?

Klaus W. schrieb:
> Das ist nicht einheitlich, deshalb würde ich es nicht zu einer Religion
> ausarten lassen.

Natürlich nicht: nur erkennt man am Sprachgebrauch, welchen Hintergrund 
der Frager hat.

Klaus W. schrieb:
> Es gibt die Meinung, daß es in C++ nicht Methoden heißen darf.

Nun, der Begriff kommt einfach nicht vor in C++.

> Allerdings ist C++ jetzt auch nicht die einzige Sprache in der OO-Welt,
> und wer in mehreren Ecken unterwegs ist, sieht das entspannter.

Es ging aber um C++.

Und wenn man ein Artefakt hat, das aus bspw. C++ und Java besteht, kann 
es sehr helfen, die Begriffe korrekt zu verwenden (wie beim Arzt eben).
#6718847
Lesenswert?

Wilhelm M. schrieb:

> Wahrscheinlich denkst Du immer noch, inline sei dazu da, einen
> Funktionsaufruf wegzuoptimieren. Das ist falsch. Dazu müsste man aber
> wirklich auch nur einmal konkret googlen. Ein Funktionsinlining wie Du
> es meinst machen die Compiler heute eh schon sofern möglich. Optimierung
> ist Compilers Aufgabe.
>
> Inline hat heute die Bedeutung, eine Verletzung der ODR auszuschließen.

Ich muss nochmal auf inline zurückkommen. Ich möchte jetzt keine 
Diskussion anfangen, aber falsch lag ich nicht. Wenn du deinen Breymann 
gefunden hast, kannst du bitte Seite 146 nachschlagen. Auch habe ich auf 
cppreference nachgelesen. Dort steht das Selbe wie im Breymann.

Das andere hat mit extern inline zu tun. Um ODR nicht zu verletzen muss 
eine externe inline Definition vorhanden sein. Das hat jedoch erstmal 
nichts mit der Wegoptimierung des Funktionsaufrufes selbst zu tun. Ob 
der Compiler automatisch inline macht oder nicht oder dem Wunsch des 
Programmierers nachkommt oder doch nicht entscheidend der Compiler, ja, 
aber wenn er inline macht, dann wird ein Funktionsaufruf eingespart und 
das Programm wird schneller.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren