C++ how to overload operators for member variables - c++

If I have a struct:
typedef struct Foo
{
std::function<bool()> func;
}Foo;
and I have a void function
void bar(){std::cout << "hey";}
and I want to be able to do this:
Foo f;
f.func = bar // f.func == func(){std::cout << "hey"; return true;}

The first thing is that the function type for void bar() {} is void() and not bool(), so func should be:
std::function<void()> func;
Second thing: it is unclear what "C++ how to overload operators for member variables" means. If you want to make your code compile then the above change is sufficient. The operator you can overload is void operator()() { func(); } if you want to call f();.
If you want to keep bool() function type and still be able to call void() function then you could use a lambda, which would call bar and return true:
f.func = [](){ bar(); return true;};

Related

Can we write a function which returns a function pointer to a function template?

Is it possible to write a function or method which can return a pointer to a template function or template method?
Example:
#include <iostream>
struct X1 {
static void Do(auto n) { std::cout << "1" << n << std::endl; }
// static auto GetPtr() { return X1::Do; } // how to write such a function?
};
struct X2 {
static void Do(int n) { std::cout << "2" << n << std::endl; }
//static auto GetPtr(){ return &Do; }
};
template <typename T> T magic(bool b, T t1, T t2) { return b ? t1 : t2; }
int main() {
auto l1 = magic(true, X1::Do, X2::Do);
// should be replaced by:
// auto l1 = magic( true, X1::GetPtr(), X2::GetPtr() );
l1(100);
}
If I compile the above out-commented functions, I got from gcc:
main.cpp:1845:39: error: unable to deduce 'auto' from 'X1::Do'
Background: I am currently trying to understand the overload resolution in same cases. In the given case you see that the overload for int is taken because one function pointer only has an int parameter so the second pointer overload can be found.
I was triggered by that question: Ternary operator applied to different lambdas produces inconsistent results
Here in an answer was suggested, that a lambda should be able to provide a conversion operator to a function pointer... and I did not see it :-)
The compiler doesn't "know" in advance all your uses for X1::GetPtr (generally). It seems you are expecting the compiler to 1. recognize it is a template 2. recognize all uses for the function, and see if it can deduce all instantiations needed for the template "for free", so to speak - in your case only the use in magic, but this is not general.
There is no such mechanism in C++ and the compiler must know the type of the function when it parses it, or recognize it as a template (and not guess it).
Simply put, I think you are expecting the compiler to do something too difficult, and it can't. As such, you will have to do the template resolution yourself:
template<typename N>
static auto GetPtr() { return &X1::Do<N>; }
and call it with
magic(true, X1::GetPtr<int>(), X2::GetPtr());
No you cannot return a pointer to a function template, because a function template is not a function. It is a template.
// static auto GetPtr() { return X1::Do; } // how to write such a function?
You need & to get a pointer to a member function, though Do is not a member function it is a member function template. You could return a pointer to X1::Do<int> or to X1::Do<double> but there is no pointer to X1::Do.
You can however return a functor with an overloaded call operator and that operator can be a template:
struct foo {
template <typename T>
void operator()(const T& t) {}
void operator()(int x){}
};
foo magic() { return foo{}; }
int main() {
magic()(3); // calls operator()(int)
magic()("hello world"); // calls operator()<const char[12]>
}
After rereading your question and the Q&A you link, I think you are maybe looking for this:
#include <iostream>
struct X1 {
static void Do(auto n) { std::cout << "1" << n << std::endl; }
static auto GetPtr() { return &X1::Do<int>; }
};
struct X2 {
static void Do(int n) { std::cout << "2" << n << std::endl; }
static auto GetPtr(){ return &Do; }
};
template <typename T> T magic(bool b, T t1, T t2) { return b ? t1 : t2; }
int main() {
auto l1 = magic( true, X1::GetPtr(), X2::GetPtr() );
l1(100);
}
As stated above, you cannot get a member function pointer to X1::Do but you can get a pointer to X1::Do<int>.
And as you are refering to conversion of lambdas to function pointers: Also lambdas with auto argument can only be converted to function pointers after choosing the argument type. Consider the example from cppreference:
void f1(int (*)(int)) {}
void f2(char (*)(int)) {}
void h(int (*)(int)) {} // #1
void h(char (*)(int)) {} // #2
auto glambda = [](auto a) { return a; };
f1(glambda); // OK
f2(glambda); // error: not convertible
h(glambda); // OK: calls #1 since #2 is not convertible
int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK
It is not possible to get a pointer to function of type auto(auto) (it isn't a type of a function to begin with). In all the calls above, after the conversion there is no auto anymore. Instead the requested type is deduced and a conversion to the respective function pointer is done.

function call operator in class or method?

class foo
{
public:
struct bar
{
bar() {}
int bar_var;
};
operator std::vector<bar>() {
return m_list;
}
private:
std::vector<bar> m_list;
int foo_var;
};
Here defined a class foo, what is the semantic "operator std:vector<bar>()" mean here? I don't think it is an overloaded function call operator.
Compile with the above code works OK
what is the semantic "operator std:vector()" mean here?
It denotes a conversion operator that allows you to use a foo object where a std::vector<bar> is expected. A conversion operator is a special kind of member function that converts a value of a class type to a value of some other type.
For example, say we have a function called func that takes a std::vector<foo::bar> as its only parameter. Now,
you can even call this function by passing a foo object instead of passing a std::vector<foo::bar> as shown below:
//--------vvvvvvvvvvvvvvvvvvvvv----------> expects std::vector<foo::bar>
void func(std::vector<foo::bar> m)
{
std::cout<<"func called"<<std::endl;
}
int main()
{
foo fObject;
//-------vvvvvvv---->passing a foo object which implicitly uses the conversion operator
func(fObject);
}
Working demo
In the above demo, func expects a std::vector<foo::bar>. But we're passing fObject which is an object of type foo and so there will be an implicit conversion of fObject to std::vector<foo::bar> using the conversion operator that you provided.
It's a conversion function. In your example, a foo will happily call that function if it's ever used in a context where a std::vector<bar> is expected. A more typical use case might look something like
class MyCustomNumberType {
private:
// Super secret number arithmetic stuff.
public:
operator double() {
// Convert to a double and return here...
}
}
MyCustomNumberType foo = /* more complicated math ... */;
double bar = foo + 1.0;

Object rvalue propagation for member function calls

I have a struct F with a function foo that has different implementation whether F is a temporary or not
struct F{
void foo() & { std::cout << "F::foo() &" << std::endl; }
void foo() && { std::cout << "F::foo() &&" << std::endl; }
};
Another struct A has a copy of F and in its function bar calls F::foo. I want to use the correct version of F::foo(). Therefore the implementation is:
struct A{
void bar() & {
f.foo();
}
void bar() && {
std::move(f).foo();
}
F f;
};
I'm wondering if I really have to provide two implementations of A::bar(). Isn't there a smart way to use std::forward to automatically decide which F::foo() should be used?
An attempt:
struct B{
void bar() {
std::forward<F>(f).foo();
}
F f;
};
However, this does not work. It calls F::foo() && every time.
Complete example
You can use a non-member function template:
struct B{
template<typename TB>
friend void bar(TB&& self) {
std::forward<TB>(self).f.foo();
}
F f;
};
Depending on other function parameters, you might want to restrict the type of TB such that is_base_of_v<B, remove_const_t<remove_reference_t<TB>>>.
No, there is no shortcut available at this point and you will need to stick to the verbose version. But have a look at p0847, "Deducing this". Not sure what the status of this proposal is, however. From the abstract:
We propose a new mechanism for specifying or deducing the value category of an instance of a class. In other words, a way to tell from within a member function whether the object it’s invoked on is an lvalue or an rvalue, and whether it is const or volatile.

How to force a call to a const qualified function overload?

I'm trying to call const function inside a class, but a non-const function with the same name exists.
Note: I can't just change names.
class MyQuestion
{
void fun()
{
cout<<"a";
}
void fun()const
{
cout<<"b";
}
void call()
{
fun();//<how to call fun() const?
}
};
Option #1:
Call that function through a pointer to a const qualified type:
void call()
{
static_cast<const MyQuestion*>(this)->fun();
// ~~~~^
}
c++11:
void call()
{
const auto* that = this;
//~~^
that->fun();
}
c++17:
void call()
{
std::as_const(*this).fun();
// ~~~~~~~^
}
Option #2:
Make the calling function a const-qualified one:
void call() const
// ~~~~^
{
fun();
}
DEMO
You have to call the function on a const pointer. For this, I recommend to create a local pointer variable:
const auto *c = this;
c->fun(); // calls fun() const
fun(); // calls fun()
Live Demo
If you need that often, and/or if you don't want to use a local variable, you could also introduce a private helper function which returns a const this pointer:
const MyQuestion *const_this() const {
return this;
}
and then call fun like this:
const_this()->fun(); // calls fun() const
fun(); // calls fun()
Live Demo
Yet another option is to write a make_const function which performs a cast to a const pointer without the need to mention the class name (it's basically a static_cast to a const pointer of a deduced type):
template <typename T>
const T* make_const(T *ptr) {
return ptr;
}
and then call fun like this:
make_const(this)->fun(); // calls fun() const
fun(); // calls fun()
Live Demo
For the sake of argument (I don't recommend the following), combining with the suggestion above, you could also introduce a global macro which expands to make_const(this):
#define const_this make_const(this)
and then call fun like this:
const_this->fun(); // calls fun() const
fun(); // calls fun()
Live Demo
I would like to add another possible solution to the excelent ones already posted.
You can help the compiler to choose the correct overload using a function pointer with the expected signature:
// Pointer to the version of fun with const
void (MyQuestion::*f)()const = &MyQuestion::fun;
(this->*f)(); // This would call the const fun
See the demo here, or the full code below:
struct MyQuestion
{
void fun()
{
std::cout<<"a";
}
void fun()const
{
std::cout<<"b";
}
void call()
{
void (MyQuestion::*f)()const = &MyQuestion::fun;
(this->*f)();
}
};
Why does this work?
Well, the type of the f pointer is void (MyQuestion::*)()const which is the same of MyQuestion::foo()const but not the same of MyQuestion::foo(), so when you take te address of the function &MyQuestion::fun the pointer f could only point to the const version.
how about overloading call() itself. Following implementation does the job. I m guessing that it is what you want to implement.
#include <iostream>
using namespace std;
class A
{
public:
void fun() { cout << "non" << endl; }
void fun() const { cout << "const" << endl; }
void call() { fun(); }
void call() const { fun(); }
};
int main()
{
A a;
a.call();
const A b;
b.call();
return 0;
}

What does operator()() in c++ do?

I'm new to C++11 thread , when reading a tutorial , I see a piece of code like this.
#include <thread>
#include <iostream>
using namespace std;
class background_task
{
public:
void operator()() const
{
cout<<"This is a new thread";
}
};
int main()
{
background_task f;
std::thread my_thread(f);
my_thread.join();
}
The output will be "This is new thread", but i don' really understand what does the function "operator()() const" mean?. In this case, it acts really the same with the constructor, is it right?.
And how can C++ have a syntax like that? I have search about related topic by using the search engine but no found no result.
Thanks in advanced.
void operator()() means an instance of the class with that operator can be called with function call syntax, with no return value, and without any parameters. For example:
background_task b;
b(); // prints "This is a new thread"
The operator() part indicates it is a call operator, the second set of empty parentheses () indicate the operator has no parameters. Here is an example with two parameters and a return value:
struct add
{
int operator()(int a, int b) const { return a + b; }
};
add a;
int c = a(1, 2); // c initialized to 1+2
Note that this syntax pre-dates C++11. You can create callable types (also referred to as functors) in C++03. The connection with C++11 is that the std::thread constructor expects something that can be called without arguments . This could be a plain function
void foo() {}
a static member function
struct foo {
static void bar() {}
};
an instance of a type such as background_task, a suitable lambda expression, a suitable invocation of std::bind, in short, anything that can be called without arguments.
It's just operator overloading and has nothing to do with C++11 or multi-threading. An overloaded operator is just a normal function with a funny name (this may be a bit oversimplified, but it's a good rule of thumb for beginners).
Your class has a function named (). That's all. Technically, you could as well have named the function foo or f or TwoParentheses.
Consider a simpler example:
#include <iostream>
class Example
{
public:
void operator()() { std::cout << "()"; }
void foo() { std::cout << "foo"; }
void TwoParentheses() { std::cout << "TwoParentheses"; }
};
int main()
{
Example e;
e.operator()();
e.foo();
e.TwoParentheses();
}
Now calling an overloaded operator like in this example in main, spelling out the entire .operator() part, is pretty pointless, because an overloaded operator's purpose is to make the calling code simpler. You would instead invoke your function like this:
int main()
{
Example e;
e();
}
As you can see, e(); now looks exactly as if you called a function.
This is why operator() is a special name, after all. In a template, you can handle objects with operator() and function pointers with the same syntax.
Consider this:
#include <iostream>
class Example
{
public:
void operator()() { std::cout << "Example.operator()\n"; }
};
void function() { std::cout << "Function\n"; }
template <class Operation>
void t(Operation o)
{
o(); // operator() or "real" function
}
int main()
{
Example object;
t(object);
t(function);
}
This is the reason why operator() is an important function in C++ generic programming, and is often required.
It has nothing to do with C++11, it's the function call overload operator. That means if you have a class like yours, you can create an instance of it and use as a function:
int main()
{
background_task bt;
bt();
}
The above main function should give the same result as your simple thread example.
it is operator over loading. the user provide an additional use to () operator. Example for static polymorphism. it is fearture of Object orieted program