How does calling this function object work? - c++

I have a class
class fobj{
public:
fobj(int i):id(i) {}
void operator()()
{
std::cout<<"Prints"<<std::endl;
}
private:
int id;
};
template<typename T>
void func(T type)
{
type();
}
If I invoke func like
Method 1:
func(fobj(1));
the message I wanted to print is printed.
I was always thinking I needed to do something like
Method 2:
fobj Iobj(1); // create an instance of the fobj class
func(Iobj); // call func by passing Iobj(which is a function object)
How does Method 1 work? I mean what exactly happens?
And how is a call made to the operator() in class fobj ?

One thing to note is that this works because your template class is taking an object by value:
template<typename T>
void func(T type) // this takes a T by value
...
because of this, it can take either an lvalue (such as an actual variable) or an rvalue (such as the temporary).
If for some reason you did want to limit func to only taking an lvalue, you could modify the function to using pass by reference:
template <typename T>
void func(T &type) // this takes a T by reference
...
using pass by reference does allow the side effect of the function being able to modify the object.

In func(fobj(1)), fobj(1) creates a temporay fobj from the literal int 1. This temporary is used to initialized the function parameter type (there's an implicit copy which the compiler may elide), and in the body of the function operator() is invoked on the function object.
I think that naming the function parameter type is a bit misleading. type is the name of the T instance (in this case a fobj) that is the function parameter.

Related

Deleting all rvalue function overloads of a class

Say I have a class object that must be captured by the caller when returning this class's object from a function call.
// no_can_rvalue *must* be captured
[[nodiscard]] no_can_rvalue a_func();
I can enforce this by deleting all rvalue function overloads, thus making it impossible to use the class functionality unless a caller has captured an object of it (doubled with nodiscard in c++17).
Is it possible to delete all rvalue function overloads of a given class in one fell swoop?
The result being equivalent to :
struct no_can_rvalue {
void f() && = delete;
void f() &;
void g() && = delete;
void g() &;
// etc
};
No, it is not possible to do so.

Ambiguous function call when Reference and Value overload exist

I have the following class:
template<typename T>
class List {
void Add(T& item) {//GOOD STUFF}
void Add(T item) {//More STUFF}
void Remove(T item) {//STUFF}
};
I am trying to use it like the following
List<MyClass> list;
MyClass obj;
list.Add(obj); //Here the compiler gets angry :((
Regarding the question I have already found the following three SO questions, but I am still not able to call either of the methods.
Ambiguous call with overloaded r-value reference function
function call ambiguity with pointer, reference and constant reference parameter
Ambiguous Reference/Value Versions of Functions
It is ambiguous which function you intend to call, because any l-value being passed as argument to a function can be implicitly converted to a reference, so the ambiguity is unavoidable, as said in Function Overloading Based on Value vs. Const Reference.
You could change this:
void Add(T item) {}
to this:
void Add(T&& item) {}
Live demo

Template type deduction according to constructor argument

I have a class template whose constructor accepts a callable whose type is a template parameter. I would like to have that type deduced so I don't have to specify it whenever instantiating the class.
Unfortunately, the type deduction doesn't work in the example below. Is there a way to get it to work?
template<typename F>
class C {
public:
C(F&& f) : m_f{f} {}
private:
F m_f;
};
class D {
public:
static int s() { return 0; }
private:
C<decltype(&s)> c {&s}; // OK
C<> c2 {&s}; // error, not enough template parameters
};
https://wandbox.org/permlink/8cphYR7lCvBA8ro4
Note this is similar to Can template parameter deduction be used in class data members? but here I'm asking about getting something similar to work, not about standard compliance.
One more note is that while re-specifiying the type of the template parameter in the example above is just a non-DRY inconvenience (which one of the answers below suggests solving with a macro), I'm not sure how it would be possible to have an instance of C with F being a non-global lambda function type (e.g. one that's defined on the spot), in case that instance is a data member. A technique which would allow that would be very powerful and useful, IMHO.
If your main goal is to avoid typing &s twice, the pragmatic solution is to define a macro:
#define CC(name,value) decltype(C{value}) name{value}
class D {
public:
static int s() { return 0; }
private:
CC(c,&s);
// lambda still not possible:
// CC(c2,[](){return 42;});
};
You could do something like this:
decltype(C{&s}) c{&s};
But I'm not aware of a way to avoid duplicating the &s.

Reference or pointer to std::vector of incomplete type

As answered here: How can an incomplete type be used as a template parameter to vector here? usage of incomplete type as template argument when instantiating a template component can result in undefined behaviour. But does that rule hold true when we have only pointer/reference to template component with incomplete type as argument? Does the instatiation happen in this case too?
For example:
// SomeAlgoInterface.hpp
#include <vector>
struct Result; // forward declaration
class SomeAlgoInterface
{
public:
virtual ~SomeAlgoInterface() = default;
public:
// the following line is definitely OK, ...
virtual void f1(const Result & result) = 0;
// ... but I'm not quite sure about the following one
virtual void f2(const std::vector<Result> & results) = 0;
};
In other words, is the code above valid or not?
The declaration is correct, so long as you don't call f2.
The compiler doesn't need to know the internal of Result class if you don't call f2. There's no storage allocation in the declaration.
If some compilation unit call f2, you need to supply the complete type for Result class, or you need another reference parameter to call f2:
void another_f(SomeAlgoInterface& i, std::vector<Result>& results)
{
i.f2(results);
}

Templated function that turns a class member function into std::function

I have a method that is invoked a lot in my code with this signature:
void foo (std::function<void(int)> func, int a) {
func(a);
}
I can easily pass a function like this to the method:
static void bar(int a);
foo(bar, 42)
Also, if I have a class instance, I can pass my the function pointer to my instance roughly like this ugly snippet:
class Baz {
bar(int a) {...}
callFoo() {
foo(std::bind(&Baz::bar, this, _1);
}
}
However, in my app, I often need to invoke foo in places where I hold a pointer to an object that has a valid member function which could serve as an argument to foo. I don't really want to give every class that happens to hold a valid pointer a method that invokes 'foo'. In fact, I would prefer that those classes don't even know about foo.
I want a method that looks like this:
template<class T>
static void callFooSugar(T* ClassPointer, [What goes here?] ClassMethod);
So I could do this:
Baz MyBaz;
callFooSugar(&MyBaz, bar);
Is there a way to write callFooSugar without resorting to macros? I am compiling with C++11.