I tried to build a minimal example:
struct Functor
{
void operator()(int& a)
{
a += 1;
}
void other(int& a)
{
a += 2;
}
};
template <typename foo>
class Class
{
public:
void function()
{
int a = 10;
foo()(a);
std::cout << a << std::endl;
}
};
int main()
{
Class<Functor> c;
c.function();
}
My question about this: Why is it even possible to call the operator on the pure type without an object? How can I call the function other the same way as I call operator()?
You're not calling it on a pure type. foo() invokes the constructor, and evaluates to a temporary foo object, on which you then invoke operator().
To do the equivalent with a "normal" member function, just do:
foo().other(a);
You are not "call[ing] the operator on the pure type without an object". The syntax foo()(a) is creating a temporary of type foo (this is the foo() part) and then calling operator() on that object with a as argument: (the (a) part).
Pure type example:
struct Functor
{
void operator()(int& a)
{
a += 1;
}
void other(int& a)
{
a += 2;
}
static void one_more(int& a)
{
a += 3;
}
};
template <typename foo>
class Class
{
public:
void function()
{
int a = 10;
foo()(a);
foo().other(a);
foo::one_more(a);
std::cout << a << std::endl;
}
};
int main()
{
Class<Functor> c;
c.function();
}
Related
I've got an abstract class that uses variable template.
template <class T>
class Abstract
{
public:
virtual void print(T t) = 0;
};
There can be any derivatives of the class like so:
class A : public Abstract<std::string>
{
public:
void print(std::string str)
{
std::cout << str << std::endl;
}
};
class B : public Abstract<int>
{
public:
void print(int number)
{
std::cout << std::to_string(number) << std::endl;
}
};
Now I want a function to return one of these derivatives so I can execute the print method. And here is my Problem:
template (class T); // error here
Abstract<T> &f(int n) // what should the return type look like?
{
if (n == 0)
{
A a{};
return a;
}
else
{
B b{};
return b;
}
}
int main()
{
A a{f(0)};
a.print("foo");
B b{f(1)};
b.print(42);
return 0;
}
So how is it be possible to return a class with unknown parameter type and call its methods?
I already tried returning derived classes without templates which works fine. As soon as templates are added code wont compile. I also tried void* and reinterpret_cast. Problem here is that I have manually to decide to what type to cast to.
So how can I return an arbitrary superclass of an abstract generic class and call its generic methods?
I think inheritance is the wrong approach here. Instead I would use specialization instead:
template<typename T>
struct Foo;
template<>
struct Foo<std::string>
{
void print(std::string const& s)
{
std::cout << s << '\n';
}
};
template<>
struct Foo<int>
{
void print(int value)
{
std::cout << value << '\n';
}
};
Then you don't need a selector to pick the object to create, just the correct type:
int main()
{
Foo<std::string> f1;
f1.print("hello");
Foo<int> f2;
f2.print(123);
}
If you really need a factor function, then it could be created like this:
template<typename T>
Foo<T> create()
{
return Foo<T>();
}
And use like
int main()
{
auto f1 = create<std::string>();
f1.print("hello");
auto f2 = create<int>();
f2.print(123);
}
Looking at this answer I can see how to call a pointer to a member function by explicitly passing in this. However, what if I want the function passed in to be a member of the current object and to use the implicit this.
I've written this, which seems to work, but is it valid code, and is there a better way (C++14 or below) avoiding the dynamic_cast<>? Source on onlinegdb.com
#include <iostream>
class Base
{
public:
// From https://stackoverflow.com/a/9779391/1270789
template<typename T, typename R>
R proxycall(T *obj, R (T::*mf)(int))
{
return (obj->*mf)(42);
}
// My attempt
template<typename T, typename R>
R proxycall(R (T::*mf)(int))
{
return ((dynamic_cast<T *>(this))->*mf)(42);
}
virtual ~Base() {}
};
class Foo: public Base
{
public:
int doFoo(int x) { std::cout << "doing foo\n"; return x / 2; }
int doCall() { return proxycall(this, &Foo::doFoo); } // OK
int doNoThisCall() { return proxycall(&Foo::doFoo); } // Is this OK?
};
int main()
{
Foo foo;
std::cout << foo.doCall() << '\n';
std::cout << foo.doNoThisCall() << '\n';
return 0;
}
Can I do something like this?
template<function_pointer_type pointer_name> struct structure1{
//here I call pointer_name(0)
};
void* function1 = [&](int a) {
return a * a;
}
structure1<function1> b;
I tried but it never compiled.
So, what's wrong with the code?
function1 is not constant expression so it cannot be used as template argument.
The lambda is not convertible to function pointer because it has a non-empty capture list.
Instead of function pointer, I suggest using a template parameter of function object, or std::function.
Function object:
template <class FunctionObject>
class A
{
private:
FunctionObject fun;
public:
A(FunctionObject f) : fun(f) {}
void f() { cout << fun(5) << endl; }
};
template <class FunctionObject>
A<FunctionObject> make_A(FunctionObject f)
{
return A<FunctionObject>(f);
}
std::function:
template <class FunctionType>
struct B
{
std::function<FunctionType> fun;
};
The usage:
void usage()
{
auto a = make_A([](int a) {return a*a; });
a.f();
B<int(int)> b;
b.fun = [&](int a) {return a*a; };
cout << b.fun(10) << endl;
}
To make this as absolutely similar to your original question as possible (using a lambda and a templated structure and so on):
#include <iostream>
template<typename F>
struct structure1 {
structure1(F x) : f(x) {}
int operator() (int a) { return f(a); };
F f;
};
int(*function1)(int) = [&](int a) {
return a * a;
};
int main() {
structure1< int(*)(int) > x(function1);
std::cout << x(4) << std::endl;
return 0;
}
I compiled and tested this with g++ -std=c++11 test.cpp
#include <iostream>
struct object1 {
object1(int v) : type(1), value(v) {}
int type;
int value;
};
struct object2 {
object2(int v) : type(2), value(v) {}
int type;
int value;
};
template <typename HeaderType>
void foo(HeaderType * hdr) {
std::cout << "foo called with type " << hdr->type << " and value " << hdr->value << std::endl;
}
// this function doesn't work
template <typename HandlerType>
void dispatch(int type, int val, HandlerType handler) {
if (type == 1) {
object1 h(val);
handler(&h);
} else {
object2 h(val);
handler(&h);
}
}
int main() {
int type = 1;
int val = 1;
// this part works
if (type == 1) {
object1 h(val);
foo(&h);
} else {
object2 h(val);
foo(&h);
}
// trying to replicate the above behavior in a more abstract way,
// ideally via a function call of the following sort
//
// dispatch(type, val, ..foo..? );
}
The above program takes an input value, uses it to decide what type of object to create, then calls a function foo with a pointer to that object.
Question: Is it possible to create this sort of abstraction where the caller of dispatch doesn't know the exact types that foo will be called with but the dispatch function doesn't know the specific function that is going to be called?
With
template <typename HandlerType>
void dispatch(int type, int val, HandlerType handler) {
if (type == 1) {
object1 h1(val);
handler(&h1);
} else {
object2 h2(val);
handler(&h2);
}
}
All branches should be valid, so handler(&h1) and handler(&h2) should be valid calls.
For that, handler may be a generic lambda (since C++14) as suggested in comment:
dispatch(type, val, [](auto a) {return foo(a);} );
or you may create your own functor:
struct foo_caller
{
template <typename HeaderType>
void operator () (const HeaderType* hdr) const {
std::cout << "foo called with type " << hdr->type << " and value " << hdr->value << std::endl;
}
};
And then call it:
dispatch(type, val, foo_caller());
Suppose we need to instantiate a function that calls some class method from inside non-trivial code.
#include <iostream>
class A
{
public:
int f() { return 1; }
int g() { return 2; }
};
template <class T, int (T::*method)()>
int func(T& x)
{
// some complex code here calling method()
return (x.*method)();
}
int main()
{
A a;
std::cout << func<A, &A::f>(a) << "\n"
<< func<A, &A::g>(a) << "\n";
return 0;
}
This code compiles and works fine. Now suppose that the two methods are actually const and non-const, like this:
class A
{
int val_;
public:
A() : val_(0) {}
int alloc() { return ++val_; }
int get() const { return val_; }
};
This time we can't use the same approach, because the member functions have different signatures due to const qualifier. Moving the problem to run time does not seem to solve anything, Is there a way to avoid rewriting func() as two functions in this situation?
Can you change passing method from template parameter to function parameter?
If yes, this works:
#include <iostream>
class A
{
public:
int f() { return 1; }
int g() const { return 2; }
};
template <class T, class F>
int func(F method, T& x)
{
// some complex code here calling method()
return (x.*method)();
}
int main()
{
A a;
std::cout << func(&A::f, a) << "\n"
<< func(&A::g, a) << "\n";
return 0;
}