Search code examples
c++templatesc++17forwarding-referenceif-constexpr

How can I merge this three c++ template function into one by universal reference or std::forward?


I've got these codes blow

template <typename T, void (*Fn)(T *)>
struct CustomF1 final
{
  void operator()(T *p) const
  {
    if (p)
      Fn(p);
  }
};

template <typename T, void (*Fn)(T)>
struct CustomF2 final
{
  void operator()(T p) const
  {
    if (p)
      Fn(p);
  }
};

template <typename T, void (*Fn)(T **)>
struct CustomF3 final
{
  void operator()(T *p) const
  {
    if (p)
      Fn(&p);
  }
};

template<typename T>
void F1(T *p) {}

template<typename T>
void F2(T p) {}

template<typename T>
void F3(T **p) {}



template <typename T, typename Deleter = std::function<void(T *)>>
using CustomUPtr = std::unique_ptr<T, Deleter>;

using Pointer1 = CustomUPtr<Foo1, CustomF1<Foo1, F1>>;
using Pointer2 = CustomUPtr<Foo1, CustomF2<Foo1, F2>>;
using Pointer3 = CustomUPtr<Foo1, CustomF3<Foo1, F3>>;

Can I use universal reference or std::forward or if constexpr or enable_if to samplify these codes.

The unique_ptr store the point of T (as T*), because these codes wrap third-party c codes, wrap the raw malloc of structs into RAII unique_ptr style.

Just merge three CustomF* struct -> one CustomF0 struct


Solution

  • You can use auto non-type template parameters:

    template <auto Deleter>
    struct FunctionDeleter {
        template <typename U>
        void operator()(U* ptr) const {
            if (ptr) {
                Deleter(ptr);
            }
        }
    };
    

    FunctionDeleter<F1<int>>, FunctionDeleter<F2<int>>, and FunctionDeleter<F3<int>> all work just fine despite having different function pointer types.