C++20 koncepty - prośba o review

C++20 koncepty - prośba o review
AL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1493
0

@kq @MarekR22 @vpiotr chyba głównie do Was ale wszystkich innych oczywiście zachęcam.
Przy okazji moich zabaw z innymi tematami, skonstatowałem, że może od razu ugryzę temat templatek i konceptów. Że siedzę na dość "bleeding-edge" systemie, to od razu C++20, bo nowe gcc dostępne od ręki.
Jako, że musiałem ostatnio sporo plików czytać, wysmażyłem taki twór:

Kopiuj

template <typename T, typename C>
concept InputStream = std::is_base_of_v<std::basic_istream<C>, T>;

template<typename T, typename C=char, typename IS=std::basic_istream<C>>
    requires (std::is_trivial_v<T> && InputStream<IS, C>)
T binary_read(IS& in)
{
    T ret;
    std::array<C, sizeof(T)/sizeof(C)> arr;
    static_assert (sizeof(T) == arr.size()*sizeof(C), "Buffer and output size have to match");
    in.read(&arr[0], arr.size());
    std::memcpy(std::addressof(ret), &arr[0], sizeof(ret));
    return ret;
}

template <std::size_t N, typename C=char, typename IS=std::basic_istream<C>>
    requires (InputStream<IS, C>)
std::array<C, N> binary_read(IS& in)
{
    std::array<C, N> arr;
    in.read(&arr[0], arr.size());
    return arr;
}

Zasadniczo to ten kod robi co chcę, pytanie czy nie można lepiej?

_13th_Dragon
  • Rejestracja: dni
  • Ostatnio: dni
1

memcpy maże po pamięci.

vpiotr
  • Rejestracja: dni
  • Ostatnio: dni
0

Ja na konceptach słabo się wyznaję, ale całość wygląda jak niezłe przekombinowanie.
Nie dałoby się tego zrobić w C++98? Albo od biedy C++11?

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
5

Jestem zwolennikiem poglądu by nie wprowadzać własnych standardów zapisu binarnego.
Obecnie, większość złożonych danych zapisuje się w postaci skompresowanych: xml-ów, json-ów, yaml-ów, gdyż są łatwiejsze w utrzymaniu.

Jeśli potrzebny ci jakiś format binarny, to są ustandaryzowane rozwiązania. Polecam google protobuf (używam w obecnym projekcie).
Zalety

  • deklaratywny opis formatu
  • mechanizmy zapewniacie wsteczną kompatybilność w domyśle
  • wparcie dla najważniejszych języków programowania: C++, C#, Dart, Go, Java, Python (łatwość komunikacji pomiędzy tymi językami).

Wsparcie konceptów nadal jest dość słabe. gcc ma najwięcej zaimplementowane, ale nadal sporo rzeczy nie jest zaimplementowana.
Efekt jest taki, że na razie nie dużo próbowałem i nie mam wprawy w użyciu konceptów.

Co do samego kodu.

Kopiuj
template<typename T, typename C=char, typename IS=std::basic_istream<C>>
    requires (std::is_trivial_v<T> && InputStream<IS, C>)
T binary_read(IS& in)

widzę dwa problemy:

  • podczas użycia musisz jawnie podać typ wartości zwracanej. Przekazywania wartości argument funkcji jako referencję będzie wygodniejsze (typ będzie podlegał detekcji) i stworzy symetrię z funkcją zapisu binarnego.
  • std::is_trivial_v nie jest najlepszym wyborem. Przykład: wskaźniki na dowolny typ. Są one trywialnie kopiowane, a nie powinny podlegać zapisowi/odczytowi. W tym miejscu zdefiniowałby swój koncept, np is_binary_serializable, żeby wyrazić jednoznacznie intencję kodu.

Do tego to iterujące UB związane z endianą i nadpisywaniem obiektów, to nie jest wielki problem, ale dość irytujący.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.