Forum: Compiler & IDEs Wie Klassen-Template Objekte in einem Array nutzen (non Template, constexpr, inline)


von Veit D. (devil-elec)


Angehängte Dateien:

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
}

:
Beitrag #6714575 wurde von einem Moderator gelöscht.
von Wilhelm M. (wimalopaan)


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
}

: Bearbeitet durch User
von M.K. B. (mkbit)


Lesenswert?

Der Code von Wilhelm sieht sehr gut aus.

Eine Anmerkung noch zum Verständnis.
Die Typen "list" und "List" haben nichts mit einer std::list zu tun. 
Auch ihr Funktion und Schnittstelle funktioniert komplett anders, weil 
es zur Compilezeit ausgewertet wird.

von Oliver S. (oliverso)


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

: Bearbeitet durch User
von Veit D. (devil-elec)


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.

von Wilhelm M. (wimalopaan)


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.

von Klaus W. (mfgkw)


Lesenswert?

... und std::byte ist relativ neu (ab C++ 17), deshalb in Büchern und 
Beispielen nicht angemessen repräsentiert.

von Wilhelm M. (wimalopaan)


Lesenswert?

Klaus W. schrieb:
> ... und std::byte ist relativ neu (ab C++ 17), deshalb in Büchern und
> Beispielen nicht angemessen repräsentiert.

Naja, ist allgemein im Umlauf seit scoped-enums ... Das war wohl c++11.

von Veit D. (devil-elec)


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?

von M.K. B. (mkbit)


Lesenswert?

Veit D. schrieb:

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

Ich glaube er meint mit back den letzten Wert aus der Liste holen. In 
der Standardbibliothek haben die Container auch front() und back().

von Wilhelm M. (wimalopaan)


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).

von M.K. B. (mkbit)


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
};

von Wilhelm M. (wimalopaan)


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.

von Veit D. (devil-elec)


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.**

von Wilhelm M. (wimalopaan)


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.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

egal ob ich cstddef inkludiere oder
enum class byte : uint8_t {};
selbst definiere, es kompiliert nicht.
Die inits gefallen dem Compiler nicht.
error: cannot convert 'int to 'byte'

@ Oliver:
> schrieb:
Danke für das Fundstück.

von Wilhelm M. (wimalopaan)


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 ...

: Bearbeitet durch User
von Oliver S. (oliverso)


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

: Bearbeitet durch User
von Veit D. (devil-elec)


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.

von Wilhelm M. (wimalopaan)


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.

von M.K. B. (mkbit)


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.

von Veit D. (devil-elec)


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 ...

von Veit D. (devil-elec)


Lesenswert?

Übrigens, was gibt es für neue Erkenntnisse zum Begriff 'Methode'?

von Wilhelm M. (wimalopaan)


Lesenswert?

Veit D. schrieb:
> Übrigens, was gibt es für neue Erkenntnisse zum Begriff 'Methode'?

Ich bin leider nicht zu Hause und habe deswegen keine Zugriff auf den 
Breymann.
Jedoch glaube es: in C++ spricht man von Funktionen: Elementfunktionen 
und freie Funktionen (member functions and free functions). Methode 
kommt in C++ nicht vor.

von Klaus W. (mfgkw)


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.

von Wilhelm M. (wimalopaan)


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).

von Klaus W. (mfgkw)


Lesenswert?

Wilhelm M. schrieb:
> Und wenn man ein Artefakt hat, das aus bspw. C++ und Java besteht, kann
> es sehr helfen, die Begriffe korrekt zu verwenden

Ja, schon.
Nur ist die Frage, was korrekt ist. :-)

von Veit D. (devil-elec)


Lesenswert?

Hallo,

einigen wir uns auf Member Funktion. Member sind sowieso vorhanden.  :-)
Frieden gestiftet?
Wünsche ein ruhiges Wochenende.

von Veit D. (devil-elec)


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.

von M.K. B. (mkbit)


Lesenswert?

Veit D. schrieb:
> Ich muss nochmal auf inline zurückkommen. Ich möchte jetzt keine
> Diskussion anfangen, aber falsch lag ich nicht.

Nachdem das standardisiert ist, gibt es da auch nichts zu diskutieren.
https://eel.is/c++draft/dcl.inline

Ist zwar nur der Entwurf für den Standard, sollte sich aber nicht 
grundlegend unterscheiden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.