Listings Fertig/C++-Tricks 7: auto als Non-Type-Templateparameter


Listing 1: Einfaches Erstellen verschiedener std::integral_constant in C++17
template<auto v>
using constant = std::integral_constant<decltype(v), v>;

constexpr constant<10>   c1;
constexpr constant<true>  c2;
constexpr constant<'a'>  c3;

-------

Listing 2: Implementierung von join zum Zusammenführen zweier std::array
template<typename T, size_t N1, size_t N2>
constexpr auto join(std::array<T, N1>& a, std::array<T, N2>& b)
{
    std::array<T, N1 + N2> ret{};

    auto copy = [&, i = 0](const auto& ar) mutable {
      for(const auto& e : ar) {
        ret[i] = e;
        ++i;
      }
    };

    copy(a);
    copy(b);

    return ret;
}

-------

Listing 3: Implementierung von join mit beliebigem std::array-ähnlichen Container
template<template<typename, size_t> class C,
    typename T,
    size_t N1,
    size_t N2>
constexpr auto join(C<T, N1>& a, C<T, N2>& b)
{
    C<T, N1 + N2> ret{};

    auto copy = [&, i = 0](const auto& ar) mutable {
      for(const auto& e : ar) {
        ret[i] = e;
        ++i;
      }
    };

    copy(a);
    copy(b);

    return ret;
}

-------

Listing 4: unique_ptr für std::FILE mit eigenem Deleter fclose
int main()
{
    auto p = std::unique_ptr<FILE, decltype(&fclose)>{
      fopen("SomeFile.txt", "r"), &fclose};
}

-------

Listing 5: C++20-Lambda als Deleter, nur als Templateparameter
int main()
{
    auto p = std::unique_ptr<FILE, decltype([](FILE* f) { fclose(f); })>{
      fopen("SomeFile.txt", "r")};
}

-------

Listing 6: Implementierung von UniquePtrDeleter mit auto als Non-Type-Templateparameter
namespace details {
    template<auto DeleteFn>
    struct UniquePtrDeleter
    {
      template<class T>
      void operator()(T* ptr) const
      {
        DeleteFn(ptr);
      }
    };
}  // namespace details

-------

Listing 7: unique_ptr_deleter-Alias zu unique_ptr mit UniquePtrDeleter
int main()
{
    auto p = unique_ptr_deleter<FILE, fclose>{fopen("SomeFile.txt", "r")};
}

-------

Listing 8: Rückgabewert von fclose prüfen
namespace details {
    template<auto DeleteFn>
    struct UniquePtrDeleter
    {
      template<class T>
      void operator()(T* ptr) const
      {
        assert(0 == DeleteFn(ptr));
      }
    };
}  // namespace details
