Pattern A parameter that can take a pointer to a function or Functor

I am trying to write a resource shell compatible with RAII, and I am fixated on how to form the semantics of the template parameters.

For example, I can write a function to delete my resource:

void int_cleaner(int val) {
    std::cout << "Value of " << val << " has been cleaned up." << std::endl;
}

Or I could write this as a Functor:

struct int_deleter {
    void operator()(int val) const {
        std::cout << "Value of " << val << " has been cleaned up." << std::endl;
    }
};

But here, where I am stuck: if I want to pass this into my resource shell, I need to change the way the template parameter is defined.

If I write resourceas follows:

template<typename T, typename Deleter>
class resource {
};

This works great with a functor, but not with the function itself.

int main() {
    resource<int, int_deleter> res; //Compiles fine
    //resource<int, int_cleaner> res2; //Does Not Compile
    return 0;
}

And vice versa, if I write the template parameters as follows:

template<typename T>
using deleter_t = void(*)(T);

template<typename T, deleter_t<T> Deleter>
class resource {
};

int main() {
    //resource<int, int_deleter> res; //Does Not Compile
    resource<int, int_cleaner> res2; //Compiles fine
    return 0;
}

Now I can write both versions of the code, but there are two reasons why I do not want to do this:

  • resource, , .
  • , , void cleaner(T const&), void(*)(T). , T, T&, T const& T&&.

, , , ?

//example:
template<typename T>
using deleter_t = void(*)(T);

template<typename T, deleter_t<T> Deleter>
class resource {
~resource() {Deleter(val);}
};
template<typename T, typename Deleter>
class resource {
~resource() {Deleter{}(val);}//Note the subtle syntax change
};
+6
2

Do

template<typename T, typename Deleter>
class resource {
};

template<auto k>
using constant_t = std::integral_constant<std::decay_t<decltype(k)>, k>;
template<auto k>
constexpr constant_t<k> constant{};

:

int main() {
  resource<int, int_deleter> res; //Compiles fine
  resource<int, constant_t<int_cleaner>> res2; //Also compiles fine
  return 0;
}

.

.

.

' d constant_t<foo> std::integral_constant<std::decay_t<decltype(foo)>, foo>, auto.

integral_constant . :

namespace notstd {
  template<class T, T t>
  struct integral_constant:std::integral_constant<T, t> {
    constexpr operator T()const{ return this->get(); }
  }
}

std::integral_constant notstd::integral_constant, . ( , ).

, .


, .

resource foo(7, int_deleter{});
resource foo2(7, int_cleaner);

. , int_cleaner .

resource foo(7, int_deleter{});
resource foo2(7, constant<int_cleaner>);

, int_cleaner, .

EBO, resource .


, resource unique_ptr<T, Deleter>, Deleter::pointer - std::optional<T> ( nullability).

template<class T>
struct nullable_opt:std::optional<T> {
  using std::optional<T>::optional;
  nullable_opt( nullable_opt const& ) = default;
  nullable_opt( nullable_opt && ) = default;
  nullable_opt& operator=( nullable_opt const& ) = default;
  nullable_opt& operator=( nullable_opt && ) = default;
  nullable_opt() = default;

  nullable_opt(std::nullptr_t) {}
};

somesuch.

+3

. , decltype. ,

resource<int, decltype(int_cleaner)> res2;

(, ), .

, , , . std::unique_ptr. , , ? , , std::shared_ptr?

+4

All Articles