I just discovered operator overloading and I am just chuffed to bits with it. In testing its uses, I came across one case that I can’t seem to make work, and I cannot find the appropriate resources to resolve.
I am trying to overload an operator which would take a function as an argument. My goal is to create a structure that can execute any function given to it (within reason, like submit commands that would follow the same general structure). Passing a struct or class would not work in this case because the internal operation of the operator would contain an execute function. If the struct or class does not have a matching member function, then the operation would not work. Such as in the following case:
struct s_test1 {
void funcA() {}
}
struct s_test2 {
void funcB() {}
}
struct s_doer {
friend void operator<<(auto, auto& s_input){
s_input.funcA(); // would fail for s_test2
s_input.funcB(); // would fail for s_test1
}
}
Ultimately, I would like to create something like this pseudo-code:
void func0(int& storage) { storage = 0; }
void func1(int& storage) { storage = 1; }
void func2(int& storage) { storage = 2; }
void alt_func(int& storage, int alt) { storage = alt; }
struct s_doer {
friend void operator<<(auto, void(*func)()){
int storage;
func(storage);
cout << storage << endl; // to check if it worked, idk
}
}
int main() {
s_doer{} << func0();
s_doer{} << func1();
s_doer{} << alt_func(); // alternatively 's_doer << alt_func(), 0' where '0' is the alt parameter of 'alt_func'
}
Here is my current implementation attempt:
struct s_doer {
friend void operator<<(auto, void (*func)()) {
std::cout << "test" << std:endl;
func();
std::cout << "test" << std::endl;
}
};
struct s_informer {
s_informer(int n) {
info = n;
}
void inform() {
std::cout << info << std::endl;
}
private:
int info;
friend void operator<<(auto, const void (*func)());
};
s_informer informer(2);
int main() {
s_doer{} << informer.inform();
}
I can’t seem to get passed the no operator "<<" matches these operands error.
Some of my other attempts have been:
friend void operator<<(auto, std::function<void()> func) {...}
template<typename input>
using Func = void(*)(input in);
friend void operator<<(auto, Func func) {...}
typedef void (*Func)(int n);
friend void operator<<(auto, Func func) {...}
Is overloading an operator with a functional input possible? Is it possible to specify parameters during overloading for the function as well?
How would it be done?
>Solution :
informer.inform() calls the function immediately, while you want to delay the call until operator<<.
You can pass a lambda that calls it, then call it in operator<<.
#include <functional>
#include <iostream>
struct s_doer
{
template <typename F>
friend void operator<<(s_doer, F &&func)
{
std::cout << "test\n";
std::forward<F>(func)();
std::cout << "test\n";
}
};
struct s_informer
{
s_informer(int n)
{
info = n;
}
void inform()
{
std::cout << info << std::endl;
}
private:
int info;
};
s_informer informer(2);
int main()
{
s_doer{} << []{informer.inform();};
}
Notice that I’ve changed the second parameter of operator<< to be templated, otherwise you won’t be able to accept capturing lambdas (which is good for generality, though this specific lambda is not capturing).
I also changed the first parameter from auto to s_doer. The former, while clever, can have unintended side effects:
template <typename> struct A {};
int main()
{
A<s_doer>{} << []{informer.inform();}; // This actually compiles! But you don't want it to.
}