C++ och dess framtid att programmera minnessäkert - Hur går utvecklingen?

Permalänk

Detta är en standardtaktik du använder. När du inte vill svara på en fråga kommer den en motfråga. Ibland om något relaterat, ibland om något orelaterat.

Skrivet av klk:

C++ har konstruktorer och destruktorer, normalt raderas allokerade minnesblock i destruktorn. Det gör de flesta och gör man det så är problemet löst med minnesläckor (oftast i alla fall).

Det du pratar om här är väl RAII? (Jag frågar så vi kan vara överens om terminologin.) Det löser en klass av problem, men inte alla.

Skrivet av klk:

Har jag förstått rätt är det huvudsakliga problemet med att skriva/läsa till områden man inte får läsa/skriva från

Hur många sätt finns det att skjuta sig i foten? shared_ptrs skyddar mot minnesläckor men jag skulle nog säga att det är ännu viktigare att du inte råkar ut för stale pointer-problematik. Du kommer inte att ha kvar pekare till objekt som du tagit bort någon annanstans i koden. För så länge du har kvar en pekare i scope kommer inte objektet tas bort. Med shared_ptr riskerar du inte heller double deletes.

Låt mig formulera om frågan som du undvek genom att ställa en motfråga; kan man vara emot smart pointers och samtidigt använda sig av dem? Det känns lite inkonsekvent. Eller är det bara när man lär sig programmera som man får gå i livets hårda skola och köra manuell minneshantering? När man väl lärt sig är det kanske acceptabelt att använda smart pointers?

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Detta är en standardtaktik du använder. När du inte vill svara på en fråga kommer den en motfråga. Ibland om något relaterat, ibland om något orelaterat.

Jag förstår inte, har jag sagt att jag aldrig använder smartpointers? Kommer inte ihåg men kan inte tänka mig att jag sagt det för det stämmer inte. I "skitkod" som jag brukar kalla domänspecifik kod använder jag det ofta. Har även skrivit "egna" smartpointers fast då för annan typ av hanering, små hjälpklasser för att hantera objekt.

Skrivet av Ingetledigtnamn:

Det du pratar om här är väl RAII? (Jag frågar så vi kan vara överens om terminologin.) Det löser en klass av problem, men inte alla.

Japp, och som jag skrev ovan, i skitkod är det mitt vanliga

Annan kod som är skriven för att återanvändas och skall vara smart, där läggs mycket tid för att få det hela så optimerat som möjligt och eftersom det återanvänds är det säkrare. Skitkod är fullt med unika lösningar för olika typer av situationer och måste han en annan typ säkerhet.

Skrivet av Ingetledigtnamn:

Hur många sätt finns det att skjuta sig i foten? shared_ptrs skyddar mot minnesläckor men jag skulle nog säga att det är ännu viktigare att du inte råkar ut för stale pointer-problematik. Du kommer inte att ha kvar pekare till objekt som du tagit bort någon annanstans i koden. För så länge du har kvar en pekare i scope kommer inte objektet tas bort. Med shared_ptr riskerar du inte heller double deletes.

För mig är det mycket sällsynt att använda shared_ptrs, det är enligt mig dålig design. Viktigt att veta vem ägaren är till data. När saker flyttar omkring blir koden mycket svårare att hantera.
För varje shared_ptr har jag säkert +50 unique_ptr.

Skrivet av Ingetledigtnamn:

Låt mig formulera om frågan som du undvek genom att ställa en motfråga; kan man vara emot smart pointers och samtidigt använda sig av dem?

Men jag är inte emot dem
De har sin uppgift och där det passar använder man dem.
Hade inte använt dem om man exempelvis skriver en parser men i skitkod så absolut, trådad kod så nära 100% säkert att jag använder det.

Exempel på vad som kan bli problem med för mycket stl och det här är långt ifrån något extremt exempel

/// @brief Type alias for table, which can be either a `gd::table::dto::table` or a `gd::table::arguments::table`. using table_t = std::variant< std::unique_ptr< gd::table::dto::table >, std::unique_ptr< gd::table::arguments::table > >; std::vector< table_t > m_vectorTableCache;

Vad som är så jobbigt med denna typ av lösning är att den är svår och debugga och svår för andra att förstå, normalt tänker jag mycket på att koden skall vara lätt att debugga så det behöver verkligen vara vinster om kod skrivs som ovan

Permalänk
Medlem
Skrivet av Yoshman:

Absolut, han hade helt rätt!

Sen var den minst lika viktiga insikten att för vissa fall, inklusive detta, får man nog acceptera "svengelska" då "överskuggning" inte är en nomenklatur speciellt många kommer känna igen.

Kör man med "override" och "overload" lär de flesta fatta även i ett svenskt kontext.

Jag hade inte reagerat om du inte hade frågat efter vettiga namn på svenska. Utifrån kontexten så var det helt uppenbart exakt vad du menade. Kolla bara på hur många som rör ihop parameter och argument utan att man ens tänker på det. Jag har samma känsla som du att man nog gör sig mer förstådd på "svengelska" än att envisas med att översätta alla termer till svenska. Däremot kan "svengelska" bli lite mycket i tal ibland så jag förstår viljan av att hitta svenska ord.

Däremot förstår jag fortfarande inte vad @kik menar med överlagring och varför det är så viktigt?

Permalänk
Medlem
Skrivet av jclr:

Jag hade inte reagerat om du inte hade frågat efter vettiga namn på svenska. Utifrån kontexten så var det helt uppenbart exakt vad du menade. Kolla bara på hur många som rör ihop parameter och argument utan att man ens tänker på det. Jag har samma känsla som du att man nog gör sig mer förstådd på "svengelska" än att envisas med att översätta alla termer till svenska. Däremot kan "svengelska" bli lite mycket i tal ibland så jag förstår viljan av att hitta svenska ord.

Däremot förstår jag fortfarande inte vad @kik menar med överlagring och varför det är så viktigt?

Oroa dig inte för det vet inte @klk i heller

Permalänk
Medlem
Skrivet av serafim:

Visst var APL intressant att testa och en del grupper höll på med det på rätt hög nivå, skrev till och med användagränssnitt i APL, såg också att det finns en sida om hur man skapar användargränssnitt i Dyalog APL (men man måste ha ett användarnamn och login och det har jag inte). Jag kanske testar igen men just nu är det mycket annat jag vill testa så APL får troligen vänta ett tag.

Den ständigt växande listan med intressanta saker man ska titta på nån gång i framtiden. Jag har knappt skrivit GUI kod i APL men det finns bindings för .Net så man kan skriva .Net / Windows Forms kod direkt i APL. Det finns även ⎕WC som också är win form baserat.

Permalänk
Medlem
Skrivet av jclr:

Däremot förstår jag fortfarande inte vad @kik menar med överlagring och varför det är så viktigt?

Bad AI göra en jämförelse mellan std::vector och rusts Vec. Rust behöver normalt nära dubbelt så många olika metodnamn jämfört med C++ på grund av att de saknar överlagring. Det kanske inte upplevs som så problematiskt om man inte är van vid att skriva generell kod eller skriva kod som skall återanvändas.

Men det är problem som ökar snabbt eftersom man hela tiden behöver hitta på nya namn, namn är svåra att hantera.

Ta en jämförelse, låt säga att du har 1000 skruvar till en bil, är det 1000 olika skruvar hade bilen blivit mycket dyr. Desto mer lika du kan få skruvarna desto lättare blir bilen att skruva samman.

Med överlagring är det enklare att ha samma namnuppsättning för olika typer av objekt och då slipper utvecklare läsa igenom koden. Bra namngivning i C++ och du behöver i princip inte läsa kod, du vet hur du skall använda det eftersom det följer mönster (fasta strukturer) och där är namn en viktig del.

Problemet med avsaknad av överlagring blir speciellt jobbigt i värdeklasser. I alla fall har jag inte lyckats få AI att skriva om C++ kod till något som verkar trevligt och jobba med. std::vector som här jämförs är långt ifrån det värsta exemplet, tvärtom

Med det sagt så är rust ett jättebra undervisningsspråk. För nya utvecklare är tydliga namn lättare att förstå jämfört med "smart" C++ kod

***

### Comparison of `std::vector` (C++) and `Vec` (Rust) Method Proliferation

A key difference between the C++ and Rust APIs is the number of method names. C++ leverages function overloading and context, while Rust uses distinct names to explicitly signal mutability, ownership, and error handling.

**Operation: Get an element**
* **C++** (Fewer names): `operator[]`, `at`, `front`, `back`
* **Rust** (More names, explicit): `[]` (via Index trait), `get`, `get_mut`, `first`, `first_mut`, `last`, `last_mut`

**Operation: Add an element**
* **C++:** `push_back`, `emplace_back`
* **Rust:** `push`, `insert`

**Operation: Remove an element**
* **C++:** `pop_back`, `erase`
* **Rust:** `pop`, `remove`, `swap_remove`

**Operation: Create an iterator**
* **C++** (Overloaded names): `begin`, `end` (with `const`, non-`const`, and reverse variants)
* **Rust** (Explicit names): `iter` (immutable borrow), `iter_mut` (mutable borrow), `into_iter` (take ownership)

**Operation: Change size**
* **C++** (Single method): `resize`
* **Rust** (Specific methods): `resize`, `resize_with`

**Operation: Remove elements by condition**
* **C++** (Algorithm + method): Use `std::remove_if` + `erase`
* **Rust** (Built-in methods): `retain`, `drain`, `drain_filter` (unstable)

**Operation: Append another collection**
* **C++** (Overloaded method): `insert` (with iterators)
* **Rust** (Specific methods): `append`, `extend`, `extend_from_slice`

**Operation: Handle errors on access**
* **C++** (Exception handling): `at` (throws an exception on error)
* **Rust** (Type-based handling): `get`, `get_mut` (return an `Option<&T>` type)

Permalänk
Medlem
Skrivet av jclr:

Den ständigt växande listan med intressanta saker man ska titta på nån gång i framtiden. Jag har knappt skrivit GUI kod i APL men det finns bindings för .Net så man kan skriva .Net / Windows Forms kod direkt i APL. Det finns även ⎕WC som också är win form baserat.

Har ingen windows, har inte .NET. Alla mina datorer kör Debian Linux. Har bara använt (inte kronolgisk ordning), VMS, TOPS-10, TOPS-20, UNIX, Linux (ett stort antal olika distributioner), MacOS (1-7), BSD. Men sedan 1994 bara Linux. Eftersom jag aldrig använt Windows är jag fullständigt korkad vad gäller allt Microsoft inklusive Windows. Hmm ... har hjälpt några grannar vid ett par tillfällen med deras problem med Windows och lyckades lösa deras problem genom att gissa mig fram. Funkade faktiskt men jag kände mig alltid bortkommen och korkad.

EDIT: IBM OS/360 har jag också använt, och på ett jobb även 370 (tror jag). Även SunOS och Solaris men den ena är ju en BSD och den andra en UNIX så de räknas kanske inte.

Visa signatur

Debian, bara Debian, Debian överallt

Permalänk
Medlem
Skrivet av klk:

Bad AI göra en jämförelse mellan std::vector och rusts Vec.

Varför det? Det är ändå ingen som litar på svar från en AI. Ingen vettig person i alla fall.
Varenda gång du hänvisar till någon AI, så visar du bara att du inte vet svaret själv.

Permalänk
Medlem
Skrivet av Erik_T:

Varför det? Det är ändå ingen som litar på svar från en AI. Ingen vettig person i alla fall.
Varenda gång du hänvisar till någon AI, så visar du bara att du inte vet svaret själv.

Framförallt visar @klk AI-svar som är fel utan att själv upptäcka det vilket ger ytterligare bekräftelse att han är ute och cyklar.

Permalänk
Medlem
Skrivet av Erik_T:

Varför det? Det är ändå ingen som litar på svar från en AI. Ingen vettig person i alla fall.
Varenda gång du hänvisar till någon AI, så visar du bara att du inte vet svaret själv.

Var det ironi?

AI genererade en tabell med metoder mellan std::vector och rusts Vec, jag kan inte metoderna för rust (korrekt) men frågan handlade om överlagring

Permalänk
Skrivet av klk:

... frågan handlade om överlagring

Kan du inte använda den engelska termen så vi vet vad du pratar om? Operator overloading? Function overloading? Function overloading har ett antal specialfall i C++ med constructors, conversions, new/delete och const/volatile, men vi kan nog bunta ihop dem alla i function overloading. operator"" för literals, är det en conversion eller hamnar det under operator overloading? Att bara säga överlagring är lite luddigt...

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Kan du inte använda den engelska termen så vi vet vad du pratar om? Operator overloading? Function overloading? Function overloading har ett antal specialfall i C++ med constructors, conversions, new/delete och const/volatile, men vi kan nog bunta ihop dem alla i function overloading. operator"" för literals, är det en conversion eller hamnar det under operator overloading? Att bara säga överlagring är lite luddigt...

Ber om förståelse för det är svårt för mig och veta vad andra vill ha för typ av svar om frågorna är vagt specificerade.

Men det är egentligen att bunta ihop alltihopa.
C++ använder en teknik som kallas för name mangeling eller decoration, C++ kompilatorer gör det och det är så de kan lista ut vilken metod som skall köras. Kompilatorns namn på metoden är inte samma som namnet programmeraren valt för metoden utan oftast en kombination av namn och argument.

Teoretiskt skulle det kunna vara så att många av de "nyare" språken som påstår att de valt bort överlagra (väljer ordet överlagra för att representera all form överlagring) för att det skulle göra språken svårare, egentligen gjort det för att underlätta att skriva kompilatorer. Det förenklar arbetet med att skriva en kompilator om man slipper generera namn baserat på namn och typ.
Utvecklare som gillar att hitta på nya språk vill kanske inte spendera åratal på att skriva en kompilator

Gäller också att kunna sälja in språket till utvecklare. Den uppgiften är långt ifrån enkel. Det är så svårt så om det bara skulle vara ett ge

Osäker på följande
Samma med "templates" i de nyare språken. I C++ är templates mer en del av språket medan de nyare språken har valt en slags skriptlogik som liknar templates men de kör sitt "eget språk" för att producera funktionalitet. Den lösningen skulle kunna vara en nödlösning för att få till flexibilitet utan att kompilatorn måste bli allt för komplicerad

Permalänk
Skrivet av klk:

Ber om förståelse för det är svårt för mig och veta vad andra vill ha för typ av svar om frågorna är vagt specificerade.

Men det är egentligen att bunta ihop alltihopa.

Det mesta som jag listade går att bunta ihop under function overloading-hatten. Ett namn används för flera olika funktioner och kompilatorn väljar den rätta beroende på sammanhang. Detta är det jag tror att du syftar på när du säger överlagring. Operator overloading och function overloading däremot är två väsensskilt olika saker. Operator overloading ger möjligheten att ha en bekväm notation istället för explicita funktionsanrop, som i std::cout << "Hello\n"; Detta är användbart då du i templates kan använda exempelvis operatorn + och template-koden kan instansieras för både native-typer och användardefinierade typer som definierat operator+, men jag tror inte det är detta som du ser som en nödvändig ingrediens för att ett programspråk skall lyckas.

Skrivet av klk:

C++ använder en teknik som kallas för name mangeling eller decoration, C++ kompilatorer gör det och det är så de kan lista ut vilken metod som skall köras. Kompilatorns namn på metoden är inte samma som namnet programmeraren valt för metoden utan oftast en kombination av namn och argument.

Teoretiskt skulle det kunna vara så att många av de "nyare" språken som påstår att de valt bort överlagra (väljer ordet överlagra för att representera all form överlagring) för att det skulle göra språken svårare, egentligen gjort det för att underlätta att skriva kompilatorer. Det förenklar arbetet med att skriva en kompilator om man slipper generera namn baserat på namn och typ.
Utvecklare som gillar att hitta på nya språk vill kanske inte spendera åratal på att skriva en kompilator

Namnmanglingen som du tar upp är ett icke-problem. Det är bara ett antal regler för hur funktionerna skall döpas utgående från namespace, klassnamn och parametrar. Det är mer än en eftermiddags jobb men ingenting man ligger vaken om nätterna och funderar över. Overloading resolution däremot, att välja vilken av funktionerna som skall anropas, det är en burk med mask utan like.

Vilka funktioner är kandidater? Vilka finns i scope? Några medlemsfunktioner? Några ärvda funktioner? Kanske någon template som matchar?

Sedan tittar man på alla kandidater och skall välja vilken som skall anropas. Är det en exact match mellan parametern och argumentet? Kan man nå en match med en promotion, conversion, user-defined conversion? Hade funktionen kanske ...-argument?

Sedan skall du bestämma vilken kandidat som är den bästa matchningen. Det är en massa krångliga regler med undantag. Till på köpet har dessa ändrats under årens lopp och beror alltså på vilken C++-version du kör. Och, ojdå, din bästa match var en template, men den kunde inte instansieras (enligt SFINAE så är detta inte ett fel utan bara en funktion vi skall strunta i, vidare till nästa kandidat). Att välja vilken funktion som skall anropas är magnituder svårare än själv manglingen.

Fråga din favorit-AI om overloading resolution pain points så kommer du få en lång lista med anledningar till att inte ta med function overloading i ditt nya programspråk.

Skrivet av klk:

Samma med "templates" i de nyare språken. I C++ är templates mer en del av språket medan de nyare språken har valt en slags skriptlogik som liknar templates men de kör sitt "eget språk" för att producera funktionalitet. Den lösningen skulle kunna vara en nödlösning för att få till flexibilitet utan att kompilatorn måste bli allt för komplicerad

Om du med "nödlösning" refererar till Rusts procedural macros, så är de nog tänkta till lite andra användningsområden än template-liknande funktionalitet. Men, ja, template resolution är lika utmanande som overloading resolution, så en lösning där du kommer undan med att bara ändra eller stoppa in nya tokens i tokenströmmen innan den kompileras är ofantligt mycket enklare. Den som har sett hur jobbigt C++ har haft det med templates söker nog hellre andra vägar.

Du får dock inte glömma att Rust, utöver procedural macros, även har generics och traits. Om du kisar lite så kan vi likna generics vid templates och traits vid concepts. Så jag skulle nog säga att de valt en annan väg snarare än att stämpla det som nödlösning.

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Namnmanglingen som du tar upp är ett icke-problem. Det är bara ett antal regler för hur funktionerna skall döpas utgående från namespace, klassnamn och parametrar. Det är mer än en eftermiddags jobb men ingenting man ligger vaken om nätterna och funderar över. Overloading resolution däremot, att välja vilken av funktionerna som skall anropas, det är en burk med mask utan like.

Vilka funktioner är kandidater? Vilka finns i scope? Några medlemsfunktioner? Några ärvda funktioner? Kanske någon template som matchar?

Sedan tittar man på alla kandidater och skall välja vilken som skall anropas. Är det en exact match mellan parametern och argumentet? Kan man nå en match med en promotion, conversion, user-defined conversion? Hade funktionen kanske ...-argument?

Sedan skall du bestämma vilken kandidat som är den bästa matchningen. Det är en massa krångliga regler med undantag. Till på köpet har dessa ändrats under årens lopp och beror alltså på vilken C++-version du kör. Och, ojdå, din bästa match var en template, men den kunde inte instansieras (enligt SFINAE så är detta inte ett fel utan bara en funktion vi skall strunta i, vidare till nästa kandidat). Att välja vilken funktion som skall anropas är magnituder svårare än själv manglingen.

Fråga din favorit-AI om overloading resolution pain points så kommer du få en lång lista med anledningar till att inte ta med function overloading i ditt nya programspråk.

Tack för förklaringen och då tolkar jag din text som att detta med överlagring gör det svårare att skriva en kompilator
Är vi överens?

Permalänk
Skrivet av klk:

Tack för förklaringen och då tolkar jag din text som att detta med överlagring gör det svårare att skriva en kompilator
Är vi överens?

Ja. Function overloading är en språkfiness som gör det mer komplext, men det skulle inte nödvändigtvis behöva vara lika utmanande att implementera som det är i C++. Kombinationen function overloading, templates och C++ regler gör att 1 + 1 + 1 = 666.

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Ja. Function overloading är en språkfiness som gör det mer komplext, men det skulle inte nödvändigtvis behöva vara lika utmanande att implementera som det är i C++. Kombinationen function overloading, templates och C++ regler gör att 1 + 1 + 1 = 666.

Har skrivit massor av olika parsers men jag hade inte velat byta med de som skriver en parser för C++

Permalänk
Datavetare
Skrivet av klk:

Bad AI göra en jämförelse mellan std::vector och rusts Vec. Rust behöver normalt nära dubbelt så många olika metodnamn jämfört med C++ på grund av att de saknar överlagring. Det kanske inte upplevs som så problematiskt om man inte är van vid att skriva generell kod eller skriva kod som skall återanvändas.

Men det är problem som ökar snabbt eftersom man hela tiden behöver hitta på nya namn, namn är svåra att hantera.

Ta en jämförelse, låt säga att du har 1000 skruvar till en bil, är det 1000 olika skruvar hade bilen blivit mycket dyr. Desto mer lika du kan få skruvarna desto lättare blir bilen att skruva samman.

Med överlagring är det enklare att ha samma namnuppsättning för olika typer av objekt och då slipper utvecklare läsa igenom koden. Bra namngivning i C++ och du behöver i princip inte läsa kod, du vet hur du skall använda det eftersom det följer mönster (fasta strukturer) och där är namn en viktig del.

Problemet med avsaknad av överlagring blir speciellt jobbigt i värdeklasser. I alla fall har jag inte lyckats få AI att skriva om C++ kod till något som verkar trevligt och jobba med. std::vector som här jämförs är långt ifrån det värsta exemplet, tvärtom

Med det sagt så är rust ett jättebra undervisningsspråk. För nya utvecklare är tydliga namn lättare att förstå jämfört med "smart" C++ kod

***

### Comparison of `std::vector` (C++) and `Vec` (Rust) Method Proliferation

A key difference between the C++ and Rust APIs is the number of method names. C++ leverages function overloading and context, while Rust uses distinct names to explicitly signal mutability, ownership, and error handling.

**Operation: Get an element**
* **C++** (Fewer names): `operator[]`, `at`, `front`, `back`
* **Rust** (More names, explicit): `[]` (via Index trait), `get`, `get_mut`, `first`, `first_mut`, `last`, `last_mut`

**Operation: Add an element**
* **C++:** `push_back`, `emplace_back`
* **Rust:** `push`, `insert`

**Operation: Remove an element**
* **C++:** `pop_back`, `erase`
* **Rust:** `pop`, `remove`, `swap_remove`

**Operation: Create an iterator**
* **C++** (Overloaded names): `begin`, `end` (with `const`, non-`const`, and reverse variants)
* **Rust** (Explicit names): `iter` (immutable borrow), `iter_mut` (mutable borrow), `into_iter` (take ownership)

**Operation: Change size**
* **C++** (Single method): `resize`
* **Rust** (Specific methods): `resize`, `resize_with`

**Operation: Remove elements by condition**
* **C++** (Algorithm + method): Use `std::remove_if` + `erase`
* **Rust** (Built-in methods): `retain`, `drain`, `drain_filter` (unstable)

**Operation: Append another collection**
* **C++** (Overloaded method): `insert` (with iterators)
* **Rust** (Specific methods): `append`, `extend`, `extend_from_slice`

**Operation: Handle errors on access**
* **C++** (Exception handling): `at` (throws an exception on error)
* **Rust** (Type-based handling): `get`, `get_mut` (return an `Option<&T>` type)

Fast fokuserar inte då på fel saker här? Tar vi ditt första exempel "Get an element" så finns en väldigt bra anledning varför det är fler saker att implementera för Rust: du får där extra funktionalitet som bl.a. hjälper till att garantera minnessäkerhet.

Och tar man grundfallet för en custom-container så är det i rader kod väldigt jämförbart

Tycker detta talar för Rust här. Samma mängd "jobb" (om vi nu ska häda och räkna arbetsinsats i SLOC), ur alla praktiska hänseenden samma prestanda men Rust-versionen kan ge långt fler garantier om korrekthet.

Skrivet av Ingetledigtnamn:

Det mesta som jag listade går att bunta ihop under function overloading-hatten. Ett namn används för flera olika funktioner och kompilatorn väljar den rätta beroende på sammanhang. Detta är det jag tror att du syftar på när du säger överlagring. Operator overloading och function overloading däremot är två väsensskilt olika saker. Operator overloading ger möjligheten att ha en bekväm notation istället för explicita funktionsanrop, som i std::cout << "Hello\n"; Detta är användbart då du i templates kan använda exempelvis operatorn + och template-koden kan instansieras för både native-typer och användardefinierade typer som definierat operator+, men jag tror inte det är detta som du ser som en nödvändig ingrediens för att ett programspråk skall lyckas.

Namnmanglingen som du tar upp är ett icke-problem. Det är bara ett antal regler för hur funktionerna skall döpas utgående från namespace, klassnamn och parametrar. Det är mer än en eftermiddags jobb men ingenting man ligger vaken om nätterna och funderar över. Overloading resolution däremot, att välja vilken av funktionerna som skall anropas, det är en burk med mask utan like.

Vilka funktioner är kandidater? Vilka finns i scope? Några medlemsfunktioner? Några ärvda funktioner? Kanske någon template som matchar?

Sedan tittar man på alla kandidater och skall välja vilken som skall anropas. Är det en exact match mellan parametern och argumentet? Kan man nå en match med en promotion, conversion, user-defined conversion? Hade funktionen kanske ...-argument?

Sedan skall du bestämma vilken kandidat som är den bästa matchningen. Det är en massa krångliga regler med undantag. Till på köpet har dessa ändrats under årens lopp och beror alltså på vilken C++-version du kör. Och, ojdå, din bästa match var en template, men den kunde inte instansieras (enligt SFINAE så är detta inte ett fel utan bara en funktion vi skall strunta i, vidare till nästa kandidat). Att välja vilken funktion som skall anropas är magnituder svårare än själv manglingen.

Fråga din favorit-AI om overloading resolution pain points så kommer du få en lång lista med anledningar till att inte ta med function overloading i ditt nya programspråk.

Om du med "nödlösning" refererar till Rusts procedural macros, så är de nog tänkta till lite andra användningsområden än template-liknande funktionalitet. Men, ja, template resolution är lika utmanande som overloading resolution, så en lösning där du kommer undan med att bara ändra eller stoppa in nya tokens i tokenströmmen innan den kompileras är ofantligt mycket enklare. Den som har sett hur jobbigt C++ har haft det med templates söker nog hellre andra vägar.

Du får dock inte glömma att Rust, utöver procedural macros, även har generics och traits. Om du kisar lite så kan vi likna generics vid templates och traits vid concepts. Så jag skulle nog säga att de valt en annan väg snarare än att stämpla det som nödlösning.

Jättebra sammanfattning!

Den ger också en vink kring en annan högst relevant teknisk orsak till varför det finns anledningar att välja bort vissa finesser eller i alla fall göra dem på andra enklare sätt. Förutom problematiken med minnessäkerhet är kompileringstider inte sällan en "pain-point" i stora C++ projekt, problem som direkt leder till högre kostnader p.g.a. sämre produktivitet.

Tyvärr lider Rust lite av samma åkomma här. Positiva är ändå att det inte alls är på nivån man ser i C++ som t.ex. boost::spirit och liknande. Men Rust-projekt får ändå relativt snabbt betydande kompileringstider ställd mot andra populära språk som C#, Java och framförallt Go.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av Yoshman:

Fast fokuserar inte då på fel saker här? Tar vi ditt första exempel "Get an element" så finns en väldigt bra anledning varför det är fler saker att implementera för Rust: du får där extra funktionalitet som bl.a. hjälper till att garantera minnessäkerhet.

visar det här exemplet så går det möjligen att förstå och påminner då om att "code reuse is the holy grail to software engineering"

Poängen med flexibiliteten i C++ är att det går och göra extremt flexibla objekt (mer flexibilitet jämfört med python för att ta ett exempel) och dessa kan återanvändas. Samma kod körs. Nedan är en flexibel tabell och det går att skriva ut denna tabell i mängder av olika format.
Kod som återanvänds behöver inte tänka på säkerhet eftersom den är så testad (vet att många här har annan åsikt men då har man inte tränat sig i att skriva återanvändbar kod)

Exemplet visar tekniker för att få ner antalet metodnamn (exempelvis använda tag_dispatcher för att visa vilken man menar)

auto ptable = pdocument->CACHE_Get("history"); // Get the history table from the cache gd::table::dto::table tablePrint(0u, { {"int32", 0, "index"}, {"rstring", 0, "name"}, {"rstring", 0, "line"} }, gd::table::tag_prepare{}); for( size_t u = 0; u < ptable->size(); ++u ) { auto variantName = ptable->cell_get_variant_view(u, "name" ); // sub command name for cleaner auto variantLine = ptable->cell_get_variant_view(u, "line" ); // command line arguments auto variantAlias = ptable->cell_get_variant_view(u, "alias" ); // alias if it exists std::string stringName = variantName.as_string(); if( variantAlias.is_true() == true ) // use alias if it exists { stringName += '\n'; stringName += variantAlias.as_string_view(); } std::string stringLine = variantLine.as_string(); // command line arguments stringLine = gd::math::string::format_text_width(stringLine, uMaxLineLength);// cut long lines tablePrint.row_add({ (int32_t)( u + 1 ), stringName, stringLine }); } std::string stringTable = gd::table::to_string(tablePrint, {{"divide", true}}, gd::table::tag_io_cli{}, gd::table::tag_text{}); // stringTable har nu följade resultat +---+----------+-------------------------------------------------------------------------+ | 1 | find | --source "C:\\dev\\home\\DOD\\target\\TOOLS\\" -R --segment comment | | | | --kv-format "[]:" --pattern @TASK --keys "date;name;description" | | | | --header "date;name" | +---+----------+-------------------------------------------------------------------------+ | 2 | find | --source "C:\\dev\\home\\DOD\\external\\gd" -R --pattern | | | | "@class;\\class" --keys "@class;@brief" --kv-format "!" --segment | | | | comment | +---+----------+-------------------------------------------------------------------------+ | 3 | find | --source "C:\\dev\\home\\DOD\\target\\TOOLS\\" -R --segment comment | | | | --pattern @TASK --keys | | | | "description;sample;idea;name;brief;date;assigned_to;state" --header | | | | name --brief brief --footer "date;assigned_to;state" --kv-where | | | | "assigned_to = 'per'" --logging-severity verbose --width 90 | +---+----------+-------------------------------------------------------------------------+ | 4 | find | --filter "*.h;*.cpp" -R --pattern @PROJECT --segment comment --keys | | | | "name;description;sample;idea" | +---+----------+-------------------------------------------------------------------------+ | 5 | find | --filter "*.h;*.cpp" -R --pattern @PROJECT --segment comment --keys | | | | description --header name --footer status | +---+----------+-------------------------------------------------------------------------+ | 6 | find | --filter "*.h;*.cpp" -R --segment comment --header | | | project | "project;name;title;status" --brief "summary" --keys | | | | "description;sample;idea" --footer "created;assignee;assiged_to" | | | | --prompt "pattern;kv-where" | +---+----------+-------------------------------------------------------------------------+

Permalänk
Medlem

if( variantAlias.is_true() == true )

🤔

Permalänk
Medlem
Skrivet av root:

if( variantAlias.is_true() == true )

🤔

Japp och det är för att läshastighet är prioriterat. if satser är ofta bland det viktigaste att de är lättlästa så att göra if-satser tydliga är viktigare än att få ner mängden kod

Lyft fram det i koden som är viktigt att observera

Permalänk
Medlem
Skrivet av klk:

Japp och det är för att läshastighet är prioriterat. if satser är ofta bland det viktigaste att de är lättlästa så att göra if-satser tydliga är viktigare än att få ner mängden kod

Lyft fram det i koden som är viktigt att observera

Läsbarhet nolla kom. "if x is true" är mer lättläst än "if x is true equals true".

Citat:

Kod som återanvänds behöver inte tänka på säkerhet eftersom den är så testad (vet att många här har annan åsikt men då har man inte tränat sig i att skriva återanvändbar kod)

Helt bananas. Det enda det säger är att det verkar fungera för de fall som körts. Ironiskt nog så går det ju mot att koden faktiskt blir mer testad, men det säger ingenting om att den skulle vara säker för det. Samma logik som att någon är duktig för att "jag har renoverat många badrum"; utan en besiktning så vet man inte säkert. Kan vara många badrum som är felaktigt utförda...

Ska man börja försöka skola andra så bör man ha lite fötterna, i mitt tycke. Jag vet flera här inne som arbetar eller har arbetat på stora globala marknadsledande företag, och än så länge av det jag sett från dig så ligger det inte över intro-/mellannivå hos studenter.

Visa signatur

Citera mig för svar.
Arch Linux

Permalänk
Medlem
Skrivet av Dimman:

Läsbarhet nolla kom. "if x is true" är mer lättläst än "if x is true equals true".

Det är för att du "endast" jämför bool, välj istället 20 olika typer av if satser och försök välja skriva de här så lika som möjligt. Då är valet lätt

Skrivet av Dimman:

Helt bananas. Det enda det säger är att det verkar fungera för de fall som körts. Ironiskt nog så går det ju mot att koden faktiskt blir mer testad, men det säger ingenting om att den skulle vara säker för det. Samma logik som att någon är duktig för att "jag har renoverat många badrum"; utan en besiktning så vet man inte säkert. Kan vara många badrum som är felaktigt utförda...

Inget är 100% säkert

Skrivet av Dimman:

Ska man börja försöka skola andra så bör man ha lite fötterna, i mitt tycke. Jag vet flera här inne som arbetar eller har arbetat på stora globala marknadsledande företag, och än så länge av det jag sett från dig så ligger det inte över intro-/mellannivå hos studenter.

Ok, men tills du klarar av att motivera din åsikt kommer jag nog fortsätta. fram med koden så får jag se från dessa briljanta utvecklare

Permalänk
Medlem
Skrivet av klk:

Det är för att du "endast" jämför bool, välj istället 20 olika typer av if satser och försök välja skriva de här så lika som möjligt. Då är valet lätt

Ok, men tills du klarar av att motivera din åsikt kommer jag nog fortsätta. fram med koden så får jag se från dessa briljanta utvecklare

Du tog ju upp det som exempel på återanvändbar kod?

if (variantAlias.is_true())

är väl ett steg i rätt riktning.

Skrivet av klk:

Inget är 100% säkert

Det beror på vilken nivå man tittar på, men rimligtvis så behöver man definiera ramarna och dra gränser för vad som är realistiskt och ej. Du kan formellt verifiera många saker och i olika nivåer (ta till matematiska bevis om det behövs). På en "daglig basis"-nivå så är det ju just testning av en massa olika scenarior som man använder sig av främst.

Visa signatur

Citera mig för svar.
Arch Linux

Permalänk
Medlem
Skrivet av Dimman:

Det beror på vilken nivå man tittar på, men rimligtvis så behöver man definiera ramarna och dra gränser för vad som är realistiskt och ej. Du kan formellt verifiera många saker och i olika nivåer (ta till matematiska bevis om det behövs). På en "daglig basis"-nivå så är det ju just testning av en massa olika scenarior som man använder sig av främst.

Tror du att test plockar 100% av alla möjliga fel?

Permalänk
Medlem
Skrivet av klk:

Tror du att test plockar 100% av alla möjliga fel?

Hur långt är ett snöre? Jag är ganska övertygad om att 2 testfall är 1 fler än 1 testfall.

Misstolka nu inte det jag skriver och eller dra felaktiga slutsatser. Det är ingen predikan för en speciell testform, de har alla sina för-och nackdelar. Man får avgöra när och var vad passar bäst. Det enda som inte går att argumentera emot är att utan någon form av verifiering, hur den än ser ut, så går det inte säga mycket om varken kvalitet, säkerhet eller något annat.

Jag har som exempel drivit projekt där det var rimligt att ha betydligt mer funktionstestning är unittestning, dels pga tidspress men även för att vi hade mycket externa beroenden och en kedja av händelser.

Visa signatur

Citera mig för svar.
Arch Linux

Permalänk
Medlem
Skrivet av Dimman:

Hur långt är ett snöre? Jag är ganska övertygad om att 2 testfall är 1 fler än 1 testfall.

Ok, precis. Du förstår nog att test inte är en "säker" metod.

Har diskuterat test tidigare i tråden och kanske låter bli och repetera. Tipsar istället om den här videon https://www.youtube.com/watch?v=wo84LFzx5nI
Och att du läser om det Casey kallar för "discriminated unions" eller "Tagged unions".

Permalänk
Medlem
Skrivet av klk:

Ok, precis. Du förstår nog att test inte är en "säker" metod.

Har diskuterat test tidigare i tråden och kanske låter bli och repetera. Tipsar istället om den här videon https://www.youtube.com/watch?v=wo84LFzx5nI
Och att du läser om det Casey kallar för "discriminated unions" eller "Tagged unions".

Kör du bil utan säkerhetsbälte också? Det är ju inte 100% säkert att man överlever en krasch ändå.

Visa signatur

Citera mig för svar.
Arch Linux

Permalänk
Medlem
Skrivet av Dimman:

Kör du bil utan säkerhetsbälte också? Det är ju inte 100% säkert att man överlever krasch ändå. Det är samma logik.

Du har lärt dig ett sätt att säkra kod, det finns flera

Och om någon använder "stora bolag's" kod för att bevisa bra kvalitet så har du tappat mig. Hade jag fått i uppgift att leta reda på skitkod så hade jag nog börjat söka i stora bolag.

Permalänk
Medlem

Nä men testade det på min sekundära dator i några dagar.. tröttnade och installerade in windows igen... På den tiden visste jag inte att man kunde ha dubbla OS

Permalänk
Medlem
Skrivet av klk:

Du har lärt dig ett sätt att säkra kod, det finns flera

Och om någon använder "stora bolag's" kod för att bevisa bra kvalitet så har du tappat mig. Hade jag fått i uppgift att leta reda på skitkod så hade jag nog börjat söka i stora bolag.

Jag tror vi behöver vända på steken här; hur gör du för att verifiera att olika scenarion fungerar med dina lösningar?

Visa signatur

Citera mig för svar.
Arch Linux