Augment a class / apply an aspect in pure C++ (C++11) - c++

Suppose I have a class:
class Widget {
public:
void initialize() {
// hurr-durr
};
int computeAnswer() {
return -42;
};
std::string getQuestion() {
return "The question";
};
};
It performs some computation, can do whatever it wants.
Now I want to augment it - apply an aspect, say one that logs each method call.
If I implemented this by hand, I'd implement all methods in this fashion:
int LoggingWidget::computeAnswer(){
log << 'Calling method computeAnswer';
int result = Widget::computerAnswer();
log << 'Result = ' << result;
return result;
}
I'd like the solution to be as generic as possible (I don't want to manually forward all calls), so the possible usages could include one of these (whichever is possible)
Widget* w = new LoggingWidget(); // either a class that inherits from Widget
// and automatically forwards all calls.
Widget* w = new Logging<Widget>(); // or a template that does this.
so that when I call
int result = w.computeAnswer();
The calls will be logged. Perhaps the new ellipsis operator (...) could come in handy here?

This isn't directly possible, since you can't inspect a class to see which members it has.
However, you can do something close:
Logging<Widget> w(widget);
w([&](Widget& w){
return w.computeAnswer();
});
Where Logging::operator() looks like follows:
/* somewhere in class: T wrapped; */
template<class F>
auto operator()(F&& f)
-> decltype(f(wrapped))
{
pre_log();
auto&& result = f(wrapped);
post_log(result);
return result;
}
It won't get better much better than this for totally generic code, since C++ has no (static) reflection.

Expanding on Xeo's answer, if you use decltype or result_of rather than auto && you also get copy elision.
template<typename F>
auto operator()(F &&f) -> decltype(std::forward<F>(f)(wrapped))
{
pre_log();
decltype(std::forward<F>(f)(wrapped)) result = std::forward<F>(f)(wrapped);
post_log(result);
return result;
}
In C++14 you can shorten this to:
template<typename F>
decltype(auto) operator()(F &&f)
{
pre_log();
decltype(auto) result = std::forward<F>(f)(wrapped);
post_log(result);
return result;
}

Related

chaining callables in C++

I come from the python world where I could define a chain of operations and call them in a for loop:
class AddOne:
def __call__(self, x, **common_kwargs):
return x+1
class Stringify:
def __call__(self, x, **common_kwargs):
return str(x)
class WrapNicely:
def __call__(self, s, **common_kwargs):
return "result="+s
data = 42
for operation in [AddOne(), Stringify(), WrapNicely()]:
data = operation(data)
output = data
(Note: the goal is to have complex operations. Ideally, common kwargs could be given)
What would be the equivalent in C++ if the return type can be different after each call?
I'm not sure I could find anything close but I may have search with wrong keywords…
C++ is statically typed, so options here are limited:
Create a chain of functions that can be determined at compile time.
Create functions with parameter and return type being the same
Return a type that could "store multiple alternative types" such as std::variant
For the first alternative you could create a class template that executes functions via recursive calls, but it's a bit more complex than your python code:
template<class...Fs>
class Functions
{
std::tuple<Fs...> m_functions;
template<size_t index, class Arg>
decltype(auto) CallHelper(Arg&& arg)
{
if constexpr (index == 0)
{
return std::forward<Arg>(arg);
}
else
{
return std::get<index - 1>(m_functions)(CallHelper<index - 1>(std::forward<Arg>(arg)));
}
}
public:
Functions(Fs...functions)
: m_functions(functions...)
{
}
template<class Arg>
decltype(auto) operator()(Arg&& arg)
{
return CallHelper<sizeof...(Fs)>(std::forward<Arg>(arg));
}
};
int main() {
Functions f{
[](int x) { return x + 1; },
[](int x) { return std::to_string(x); },
[](std::string const& s) { return "result=" + s; }
};
std::cout << f(42) << '\n';
}
Note: This requires the use of a C++ standard of at least C++17.
TL;DR
Use composition from ranges:
using std::views::transform;
auto fgh = transform(h) | transform(g) | transform(f);
auto fgh_x = std::array{42} | fgh; // Calculate f(g(h(x)))
// single element range ^^
// ^^ ranges::single_view{42} is an alternative
std::cout << fgh_x[0]; // Result is the only element in the array.
Demo
DIY
I've written a series of articles on C++ functional programming years ago, for some thoughts on composition you can start from this one.
That said, you can also avoid the "functional nuances" and start from scratch. Here is a generic composer of callables:
template <class F, class... Fs>
auto composer(F&& arg, Fs&&... args)
{
return [fun = std::forward<F>(arg),
...functions = std::forward<Fs>(args)]<class X>(X&& x) mutable {
if constexpr (sizeof...(Fs))
{
return composer(std::forward<Fs>(functions)...)(
std::invoke(std::forward<F>(fun), std::forward<X>(x)));
}
else
{
return std::invoke(std::forward<F>(fun), std::forward<X>(x));
}
};
}
which you'd use as:
// Store the composed function or call it right away.
composer(lambda1, lambda2, lambda3)(42);
Demo
When teaching C++ to python developers, you've got to be careful in order to overcome the "C++ is so complicated" prejudice.
In this regard, you have two options:
If you want to chain operations, you can directly nest lambdas just as in python. It's only a different syntax, see my anser below.
However, if you use the chaining more often and want to apply the linear compose(f,g,h) syntax (which save you from typing a few char's), you should generate a composer yourself. The other answers follow this path, and for brevity I'd suggest the answer of #NikosAthanasiou.
So, here is the short version: Given some variable x and assuming it is a number (as you apply +1), you can directly chain the lambdas:
auto operation = [](auto x) { return [](auto y) { return "result="+std::to_string(y); }(x+1); };
ans use it as
std::vector<int> v; // -> fill the vector v
std::vector<std::string> w;
for(auto& x : v)
{
w.push_back(operation(x));
}
Only thing which you miss is the in-place mutation from int to string. For this, see the other answers using a std::variant, but why you should? ... use it only when you really need it.

Is Object Editor a good approach if there are multiple member functions to call?

I am often annoyed by sequential calls of class member function like this (ignore new usage, it's for Qt, but it's not strictly Qt-related)
A a = new A();
a->fun1("one");
a->fun2(1, 2);
...
a->fun10("end");
I always felt that such code should be written as simple instruction, not a project dominating lines.
Simple example from Qt:
auto* spinBox = new QSpinBox();
spinBox->setRange(-100, 100);
spinBox->setValue(50);
spinBox->setSingleStep(5);
newLayout->addWidget(spinBox);
But I would prefer to do this in simple single line instead of that. So I have written something like this:
class {
public:
template<class X>
auto& operator()(X* ptr) {
this->ptr = ptr;
return *this;
}
template<class X, class R, class... Args>
auto& operator()(R (X::* fun)(Args...), Args... args) {
if(ptr == nullptr) {
std::cerr << "Editor can't edit nullptr" << std::endl;
return *this;
}
auto call = std::mem_fn(fun);
call(*static_cast<X*>(ptr), args...);
return *this;
}
template <class X>
operator X*() {
auto* result = static_cast<X*>(ptr);
ptr = nullptr;
return result;
}
private:
void *ptr = nullptr;
} EDITOR;
And now the usage:
newLayout->addWidget(EDITOR(new QSpinBox)(&QSpinBox::setRange,-100, 100)(&QSpinBox::setValue, 50)(&QSpinBox::setSingleStep, 5));
Is it good approach, except not being type-safe? (I could live with that)
---
EDIT
---
Another, type-safe approach would be:
template<class X>
class EDITOR2 {
public:
EDITOR2(X* ptr) {
this->ptr = ptr;
}
template<class R, class... Args>
auto& operator()(R (X::* fun)(Args...), Args&&... args) {
if(ptr == nullptr) {
std::cerr << "Editor can't edit nullptr";
return *this;
}
auto call = std::mem_fn(fun);
call(*ptr, args...);
return *this;
}
operator X*() {
return ptr;
}
X *ptr;
};
With usage:
newLayout->addWidget(EDITOR2<QSpinBox>(new QSpinBox)(&QSpinBox::setRange, -100, 100)(&QSpinBox::setValue, 50)(&QSpinBox::setSingleStep, 5));
But that requires to recreate editor object every time, and adds additional usage code.
Let's fight,
First opponent, vanilla approach:
auto* spinBox = new QSpinBox();
spinBox->setRange(-100, 100);
spinBox->setValue(50);
spinBox->setSingleStep(5);
newLayout->addWidget(spinBox);
Pros:
It's the way all people do this
It's pretty readable being ~30 columns wide
Cons:
It takes 5 lines
The subject of the action spinBox is repeated each time
Second opponent, fancy approach:
newLayout->addWidget(EDITOR2<QSpinBox>(new QSpinBox)(&QSpinBox::setRange, -100, 100)(&QSpinBox::setValue, 50)(&QSpinBox::setSingleStep, 5));
Pros:
It takes one line
It is somewhat a more functional programming approach
Cons:
It's a pretty long line that's hard to read
By default people's reaction will be a variant of wtf since they are not used to it
The instance name spinBox is not repeated but the class name QSpinBox now is
The final choice is yours based on how much you value each point, i did compare the second approach in one line as if you use line breaks you're essentially getting back to the original thing you were trying to fix
In my humble opinion adding a class overhead for so little is not worth it, and i am the kind of person annoyed by the cons of the original approach, the killer point being the readability loss which will most likely force you to use line breaks which in turns pretty much means you've done all this for nothing.
This is kind of like a fluent interface, except rather than having a bunch of named functions to as a builder, you just use pointers to members. It's a reasonable approach, if you're into that sort of thing (primarily opinion based), but the total lack of type safety is not ok.
Regardless std::cerr is not a good way to do error handling. throw or assert.
You can improve it a lot:
template <class T>
struct EditorImpl
{
T* ptr;
template <class F, class... Args>
Editor& operator()(F&& f, Args&&... args)
{
std::invoke(std::forward<F>(f), ptr, std::forward<Args>(args)...);
return *this;
}
T* yield() const {
return ptr;
}
};
template <class T>
EditorImpl<T> Editor(T* ptr) { return EditorImpl<T>{ptr}; }
And then you can write:
newLayout->addWidget(
Editor(new QSpinBox)
(&QSpinBox::setRange,-100, 100)
(&QSpinBox::setValue, 50)
(&QSpinBox::setSingleStep, 5)
.yield());
Though this would probably work better if the interface was already fluent:
newLayout->addWidget(
(new QSpinBox)
->range(-100, 100)
->value(50)
->singleStep(5));
But that would imply writing a bunch of new named functions, which you're definitely (probably?) not going to do.
std::invoke() is C++17, but is implementable in C++11.

Choose template based on run-time string in C++

I have an attribute vector that can hold different types:
class base_attribute_vector; // no template args
template<typename T>
class raw_attribute_vector : public base_attribute_vector;
raw_attribute_vector<int> foo;
raw_attribute_vector<std::string> foo;
Based on run-time input for the type, I would like to create the appropriate data structure. Pseudocode:
std::string type("int");
raw_attribute_vector<type> foo;
Obviously, this fails. An easy, but ugly and unmaintainable workaround is a run-time switch/chained if:
base_attribute_vector *foo;
if(type == "int") foo = new raw_attribute_vector<int>;
else if(type == "string") ...
I read about run-time polymorphism with functors, but found it quite complex for a task that is conceptually easy.
What is the best and cleanest way to make this work? I played around with boost::hana, finding that while I can create a mapping from string to type, the lookup can only be done at compile time:
auto types =
hana::make_map(
hana::make_pair(BOOST_HANA_STRING("int"), hana::type_c<int>),
hana::make_pair(BOOST_HANA_STRING("string"), hana::type_c<std::string>)
);
All possible types are known at compile-time. Any suggestions are highly appreciated. In a perfect solution, I would create the name->type mapping in a single place. Afterwards, I would use it like this
std::vector<base_attribute_vector*> foo;
foo.push_back(magic::make_templated<raw_attribute_vector, "int">);
foo.push_back(magic::make_templated<raw_attribute_vector, "std::string">);
foo[0]->insert(123);
foo[1]->insert("bla");
foo[0]->print();
foo[1]->print();
It is not required for this magic to happen at compile time. My goal is to have as readable code as possible.
I'd use an std::map that has strings as key and std::function as values. I would associate the string with a function that returns your type. Here's an example:
using functionType = std::function<std::unique_ptr<base_attribute_vector>()>;
std::map<std::string, functionType> theMap;
theMap.emplace("int", []{ return new raw_attribute_vector<int>; });
theMap.emplace("float", []{ return new raw_attribute_vector<float>; });
// Using the map
auto base_vec = theMap["int"](); // base_vec is an instance of raw_attribute_vector<int>
Of course, this solution is valid if you only know the string value at runtime.
enum class Type
{
Int,
String,
// ...
Unknown
};
Type TypeFromString(const std::string& s)
{
if (s == "int") { return Type::Int; }
if (s == "string") { return Type::String; }
// ...
return Type::Unknown;
}
template <template <typename> class>
struct base_of;
template <template <typename> class C>
using base_of_t = typename base_of<C>::type;
And then the generic factory
template <template <typename> class C>
std::unique_ptr<base_of_t<C>> make_templated(const std::string& typeStr)
{
Type type = TypeFromString(typeStr);
static const std::map<Type, std::function<std::unique_ptr<base_of_t<C>>()>> factory{
{Type::Int, [] { return std::make_unique<C<int>>(); } },
{Type::String, [] { return std::make_unique<C<std::string>>(); } },
// ...
{Type::Unknown, [] { return nullptr; } }
};
return factory.at(type)();
}
a specialization is needed for each base:
template <>
struct base_of<raw_attribute_vector> {
using type = base_attribute_vector;
};
And then
auto p = make_templated<raw_attribute_vector>(s);
Demo
I'd probably do something like this:
Features:
1 - time registration of objects by passing a named prototype
constant time lookup at runtime
lookup by any type which can be compared to std::string
-
#include <unordered_map>
#include <string>
struct base_attribute_vector { virtual ~base_attribute_vector() = default; };
template<class Type> struct attribute_vector : base_attribute_vector {};
// copyable singleton makes handling a breeze
struct vector_factory
{
using ptr_type = std::unique_ptr<base_attribute_vector>;
template<class T>
vector_factory add(std::string name, T)
{
get_impl()._generators.emplace(std::move(name),
[]() -> ptr_type
{
return std::make_unique< attribute_vector<T> >();
});
return *this;
}
template<class StringLike>
ptr_type create(StringLike&& s) const {
return get_impl()._generators.at(s)();
}
private:
using generator_type = std::function<ptr_type()>;
struct impl
{
std::unordered_map<std::string, generator_type, std::hash<std::string>, std::equal_to<>> _generators;
};
private:
static impl& get_impl() {
static impl _ {};
return _;
}
};
// one-time registration
static const auto factory =
vector_factory()
.add("int", int())
.add("double", double())
.add("string", std::string());
int main()
{
auto v = factory.create("int");
auto is = vector_factory().create("int");
auto strs = vector_factory().create("string");
}
Largely based on Jarod42's answer, this is what I will be using:
class base_attribute_vector {};
template<typename T>
class raw_attribute_vector : public base_attribute_vector {
public:
raw_attribute_vector() {std::cout << typeid(T).name() << std::endl; }
};
template<class base, template <typename> class impl>
base* magic(std::string type) {
if(type == "int") return new impl<int>();
else if(type == "float") return new impl<float>();
}
int main() {
auto x = magic<base_attribute_vector, raw_attribute_vector>("int");
auto y = magic<base_attribute_vector, raw_attribute_vector>("float");
}
Short answer: no, you can't instruct the compiler to evaluate a runtime condition in compile time. Not even with hana.
Long answer: there are some (mostly language independent) patterns for this.
I'm assuming that your base_attribute_vector has some virtual method, most likely pure, commonly called an interface in other languages.
Which means that depending on the complexity of your real problem, you probably want a factory or an abstract factory.
You could create a factory or abstract factory without virtual methods in C++, and you could use hana for that. But the question is: is the added complexity really worth it for that (possibly really minor) performance gain?
(also if you want to eliminate every virtual call, even from base_attribute_vector, you have to make everything using that class a template, after the entry point where the switch happens)
I mean, have you implemented this with virtual methods, and measured that the cost of the virtual calls is too significant?
Edit: another, but different solution could be using a variant type with visitors, like eggs::variant.
With variant, you can create classes with functions for each parameter type, and the apply method will switch which function to run based on it's runtime type.
Something like:
struct handler {
void operator()(TypeA const&) { ... }
void operator()(TypeB const&) { ... }
// ...
};
eggs::variant< ... > v;
eggs::variants::apply(handler{}, v);
You can even use templated operators (possibly with enable_if/sfinae), if they have common parts.

How to implement a lambda function for a sort algorithm involving object members, indirection, and casting?

I'm working on some code and I have a section where I do a one off sort function. To implement it I decided it was easiest to overload the operator< function. What I would prefer to do is move the implementation of the sort closer to the actual call by using some sort of boost::bind, boost::phoenix, lambda or some other type of implementation. Unfortunately I don't have access to new C++11 functionality. Below is some example code.
// In a header
struct foo
{
char * a;
char * c_str() { return a; }
}
// In a header
struct bar
{
foo * X;
bar(foo * _X) : X(_X) {}
bool operator < (const bar& rhs) const
{
return std::string(X->c_str()) < std::string(rhs.X->c_str());
}
};
struct bars : public std::vector<bar> { ... some stuff };
// Some other header
bars Bs;
// A cpp file
... other stuff happens that fills the Xs vector with objects
...::Function()
{
// Current use and it works fine
std::sort(Bs.begin(), Bs.end())
// Would like something that accomplishes this:
// std::sort(Bs.begin(), Bs.end(),
// std::string(lhs.X->c_str()) < std::string(rhs.X->c_str()))
// A non-working example of what I'm trying to do
// std::sort(Xs.begin(), Xs.end(),
// std::string((bind(bar::X->c_str(), _1)) <
// std::string((bind(bar::X->c_str(), _2)) )
}
I get lost when trying to figure out how to access the member pointers, member function and then cast the result all within a boost::bind function.
Thank you for your help.
I'm sure you can twist your way out of this using ample helpings of
Boost Phoenix bind and lambda
Boost Bind protect
However, I've learned to avoid these situations. Edit In fact, see below for one such contraption. I find this very very error prone and hard to reason about.
What you're seeing is, in essence, a violation of the Law Of Demeter. If you "just" wrote the code (not in a lambda), already it would be handling too many tasks.
So the first thing I'd do is rethink the class design.
The second thing I'd do is /extract/ different responsibilities from your comparator. Notice, that the comparator does three things:
access the c_str() of the X in lhs
access the c_str() of the X in rhs
compare the two
The first two steps are clear candidates for extraction. Let's write the generic comparer that remains first:
template <typename F>
struct compare_by_impl {
compare_by_impl(F f = F{}) : _f(std::move(f)) {}
template <typename T, typename U>
bool operator()(T const& a, U const& b) const {
return _f(a) < _f(b);
}
private:
F _f;
};
As always, it's nice to have factory function that will deduce the accessor type (in case you can get away with just using Phoenix there, it will save you specifying the (arcane) typenames involved in the expression templates):
template <typename Accessor>
compare_by_impl<Accessor> comparer_by(Accessor&& f) {
return compare_by_impl<Accessor>(std::forward<Accessor>(f));
}
Now you could already move the implementation with your sort call:
void Function()
{
struct accessX_c_str {
std::string operator()(bar const& b) const {
return b.X->c_str();
}
};
std::sort(Bs.begin(), Bs.end(), comparer_by(accessX_c_str()));
}
I'd personally leave it there.
Here's some more twisted contraptions:
// to avoid `comparer_by`
std::sort(Bs.begin(), Bs.end(), phx::bind(accessX_c_str(), arg1) < phx::bind(accessX_c_str(), arg2));
// to avoid any helper types (!?!?!? untested!)
std::sort(Bs.begin(), Bs.end(),
phx::construct<std::string>(phx::bind(&foo::c_str, phx::lambda [ phx::bind(&bar::X, arg1) ](arg1)))
< phx::construct<std::string>(phx::bind(&foo::c_str, phx::lambda [ phx::bind(&bar::X, arg1) ](arg2)))
);

Wrapping C functions in auto objects without code duplication

In C++03, when you were to wrap a bunch of C functions in a class to create an 'auto object', you had to customize the object to the type of functions it encapsulated. As an example, to wrap a windows file HANDLE, you needed to call CloseHandle() in the destructor and CreateFile() in the constructor. The constructor would need to mimic the function signature of the CreateFile() function, sans the file HANDLE variable (since it's being managed).
Anyway, what I'd like to know is if it's possible to use the new features of C++11 to create a single generic class that can be used to wrap any type of resource by only providing an implementation for creation and deletion?
One problem I foresee is that the creation function, such as noted above with CreateFile(), can taken any number of parameters. Is there a way to auto-magically generate a templated constructor that mimics the signature of the function? Variadic Parameters come to mind, but I have not yet used them.
Has anyone tried writing something like this?
EDIT: Some code to help illustrate (pseudo):
template<typename Res, FunctionPtrToCreatorFunc Func, typename... Arguments>
class creator
{
public:
operator()(Res &r, Arguments... Args)
{
Func(r, /*use args?*/ Args); // Allocate resource, ie. CreateFile(r, args)
}
};
template<typename Res, FunctionPtrToDeleterFunc Func>
class deleter
{
operator()(Res &r)
{
Func(r); // delete the resource, ie. CloseHandle(r)
}
};
Then this will be the implementation of my super auto object:
template<typename Res, typename Creator, typename Deleter>
class auto_obj
{
public:
auto_obj(/*somehow copy Args from Creator class?*/)
{
Creator(_res, /*args?*/);
}
~auto_obj()
{
deleter(_res);
}
Res _res;
};
Yes, this has a similar structure to shared_ptr or unique_ptr, but instead the constructor will be the one that creates the resources by developer written creator and deleter classes. I have a feeling that std::bind may play a role in this, but I have never used it.
Here is a stab at it:
#include <utility>
#include <type_traits>
#include <cstddef>
A more friendly way to wrap up a function. I move the signature boilerplate to this template, instead of messing up the actual RAII class below. This also allows full fledged function objects to be used, as well as functions, in the RAII class below:
template< typename FuncSig, FuncSig func >
struct Functor {
template<typename... Args>
auto operator()(Args&&... args) const
-> decltype( func(std::forward<Args>(args)...) )
{ return ( func(std::forward<Args>(args)...) ); }
};
One operation that is needed for more than basic functionality is the ability to "null" a handle, allowing invalid handles to exist, and allowing handles to be moved around. Zeroer is my default function object for "null"ing a handle:
struct Zeroer {
template<typename T>
void operator()( T& t ) const {
t = 0;
}
};
RAII_handle herself. You pack the creation and destruction signatures into it, and it forwards construction to the underlying data. .close() lets you close the RAII_handle early, which is a common requirement in practice. You access the underlying data via operator* or operator->, and while this makes it look pointer-like, RAII_handle does not obey pointer semantics. It is a move-only type.
template< typename T, typename Creator, typename Destroyer, typename Nuller=Zeroer >
struct RAII_handle {
RAII_handle( std::nullptr_t ):
data()
{
Nuller()(data);
}
RAII_handle( RAII_handle const& ) = delete;
RAII_handle( RAII_handle && o ):data(std::move(o.data)) {
Nuller()(o.data);
}
RAII_handle& operator=( RAII_handle const& ) = delete;
RAII_handle& operator=( RAII_handle && o ) {
data = std::move(o.data);
Nuller()(o.data);
return *this;
}
template<typename... Args>
RAII_handle( Args&&... args ):
data( Creator()(std::forward<Args>(args)...) )
{}
auto close()->decltype( Destroyer()(std::declval<T&>()) ) {
auto retval = Destroyer()(data);
Nuller()(data);
return retval;
}
~RAII_handle() {
close();
}
T& get() { return data; }
T const& get() const { return data; }
T& operator*() { return get(); }
T const& operator*() const { return get(); }
T* operator->() { return &get(); }
T const* operator->() const { return &get(); }
private:
T data;
};
Now, some test code. My file handles will be unsigned char, and opening/closing will simply test if things are not working right.
#include <iostream>
typedef unsigned char HANDLE;
HANDLE CreateFile( char const* name ) {
std::cout << name << "\n";
return 7;
}
bool CloseFile( HANDLE h ) {
if (h) {
--h;
std::cout << (int)h << "\n";
return true;
} else {
std::cout << "already closed\n";
return true;
}
}
Once you have your open/close functions or function objects, here is how you make the type of the FileHandle:
typedef RAII_handle< HANDLE, Functor< HANDLE(*)( char const* ), CreateFile >, Functor< bool(*)(HANDLE), CloseFile > > FileHandle;
You can support entire overload sets by simply creating a function object that forwards to a fixed function name, instead of to a fixed function pointer. Basically take Functor above, remove the template signature and pointer, and replace the use of func with actual use of your function name.
Suddenly your function object represents not calling one function, but calling an entire overload set.
Fancier work can even support multiple functions, allowing one function object to support calling either CreateFile or CreateFileEx depending on what arguments are passed in.
And here is our trivial test code:
int main() {
FileHandle bob("hello.txt");
HANDLE value = *bob; // get the HANDLE out of the FileHandle
bob.close(); // optional, to close early
}
Requirements: your CloseFile must accept Nuller()(std::declval<T&>()) and not behave badly. The default Nuller()(...) just assigns zero to your T, which works for many handle types.
It supports move semantics, allowing you to return these from a function, but I didn't include a Copier argument (which I'd expect would be required for any RAII objects that can be copied).
Live example with very slightly different code.