19 maja 2015

[C++] Aggregate, trivial classes, standard-layout

Nowy standard wprowadza kilka definicji, które trzeba przyswoić.

Aggregate


Agregaty (tablice lub klasy), które mogą być inicjalizowane nawiasami klamrowymi (nie ma to nic wspólnego z std::initializer_list).
Jeżeli elementów, które podamy w klamrach będzie mniej, niż tych zadeklarowanych, to dla brakujących elementów zostanie (o ile to możliwe) zawołany konstruktor domyślny.
Agragaty, nie mogą mieć:
  • konstruktora stworzonego przez użytkownika (ale user-declared jest w porządku)
  • niestatycznych składowych zainicjowanych w miejscu deklaracji
  • prywatnych lub chronionych niestatycznych pól składowych
  • klas bazowych
  • metod wirtualnych
#include <iostream>
#include <string>
#include <vector>

struct AggregateClass {
//  AggregateClass() {}           // ERROR - stworzone przez użytkownika
    AggregateClass() = default;   // OK - "user-declared"

    int a;
    std::string b;
    std::vector<double> c;
};

int main() {
    AggregateClass ag = {3, "text", {1.41, 3.14}};
}

Trivial classes


Klasy trywialne wspierają statyczną inicjalizację typu. Klasa trywialna to klasa, która ma trywialny konstruktor domyślny i jest trywialnie kopiowalna.
Klasa trywialnie kopiowalna (trivially copyable), to taka, której instancje mogą być kopiowane bitowo np. przy pomocy std::memcpy().

W opisie metod traitsów, są szczegółowe wymagania:
#include <iostream>
#include <type_traits>

struct Trivial {
    Trivial() = default;

    int value;
};

int main() {
    std::cout << std::boolalpha;

    std::cout << std::is_trivial<Trivial>::value << "\n";
    std::cout << std::is_trivially_copyable<Trivial>::value << "\n";
    std::cout << std::is_trivially_default_constructible<Trivial>::value << "\n";
}
Wynik:
true
true
true

Standard-layout


Typy standard-layout mają takie same ułożenie pól w pamięci jak struktury w języku C. Warunki, które muszą spełniać

POD - przestarzałe od C++20


Typy POD, są kompatybilne bitowo ze strukturami języka C. W nowej wersji standardu wprowadzono nową (uszczegółowioną) definicję typów POD (plain old data). Typem POD jest klasa, która jest jednocześnie trivial classes i standard-layout i jest to właściwość spełniona (rekursywnie) dla wszystkich jej pól.
W C++20 std::is_pos zostało usunięte.

Przykład dla POD i standard-layout

#include <iostream>
#include <type_traits>

struct A {
    int field;
};

struct B {
    int field1;
private:
    int field2;
};

int main()
{
    std::cout << std::boolalpha;

    std::cout << "A trivial: " << std::is_trivial<A>::value << "\n";
    std::cout << "A standard_layout: " << std::is_standard_layout<A>::value << "\n";
    std::cout << "A pod: " <<std::is_pod<A>::value << "\n";

    std::cout << "\n";
    std::cout << "B trivial: " << std::is_trivial<B>::value << "\n";
    std::cout << "B standard_layout: " << std::is_standard_layout<B>::value << "\n";
    std::cout << "B pod: " << std::is_pod<B>::value << "\n";
}
Wynik:
A trivial: true
A standard_layout: true
A pod: true

B trivial: true
B standard_layout: false
B pod: false

Brak komentarzy:

Prześlij komentarz