C++ template - compile member function based on arguments - c++

Suppose that a class has a member function which should accept either a double(double) function or a class instance with a "MyStructFunc" public member function as an argument:
#include<functional>
#include <type_traits>
struct Caller
{
// (1.)
double call(std::function<double(double)> func) { return func(1); }
// (2.)
template<typename T>
double call(const T& S) { return S.MyStructFunc(2); }
};
So, for example, we can pass
double myFunc(double x) { return x * x * x; }
or
struct myStruct
{
double MyStructFunc(double x) const { return x * x; }
};
like this:
int main()
{
Caller c;
myStruct ms;
c.call(myFunc);
c.call(ms);
}
Unfortunately, I get an error. Could you please help me make it work? Thank you for your help!

function pointer is not a std::function, so your template method is a better match.
You might use SFINAE to restrict your template method:
// (2.)
template<typename T>
auto call(const T& S) -> decltype(S.MyStructFunc(2)) { return S.MyStructFunc(2); }
Demo

Related

C++ pass pointer to member as template argument

I have a bunch of very similar functions:
void foo1(Obj o) {
bar(o.a);
}
void foo2(Obj2 o) {
bar(o.b);
}
void foo3(Obj3 o) {
bar(o.c);
}
How can I reduce the duplicating of code? Can I do something like:
template<typename T, pointerToMember>
void foo(T o) {
bar(o.pointerToMember);
}
And then create all functions like:
foo<Obj, Obj.x>;
...
?
Yes it is possible to have a pointer to member as template parameter:
#include <string>
struct Obj {
int a,b,c;
};
void bar(int x){}
template<typename T, int (T::*pointerToMember)>
void foo(T o) {
bar(o.*pointerToMember);
}
int main() {
Obj x;
foo<Obj,&Obj::a>(x);
}
However, there are different ways that would make the call less verbose. You could pass the member pointer as parameter to be able to deduce it, that would allow to call it as
foo(x,&Obj::a);
Last not least, you could call bar directly
bar(x.a);

Error in passing function to function template

I have function templates :
template<typename T>
inline T fun3(T &x1, T &x2)
{
return std::pow(x1,2.0) + std::pow(x2,2.0);
}
template<typename T, typename U>
inline T fun5(U &a)
{
return (T(4.0+a*(-2.0),5.0+ a*3.0));
}
template<typename F, typename T>
void min(F fun1, T& v)
{
double x={10.0};
v=fun1(x);
}
int main()
{
double val;
min(fun3(fun5),val);
std::cout<<"value = "<<val<<"\n";
return 0;
}
I want to evaluate fun3(fun5(x)) and have functions as shown above. But getting error as no matching function for call to ‘Function5<double>::fun5(<unresolved overloaded function type>)’ obj1(o5.fun5(o3.fun3),-2.0,0.0,location,value);
Can someone explain how can I pass function to min()?
What will change if all these functions were class templates like:
template<typename T>
class Fun3 {
inline T fun3(T &x1, T &x2)
{
return std::pow(x1,2.0) + std::pow(x2,2.0);
}
};
template<typename T, typename U>
class Fun5 {
inline T fun5(U &a)
{
return (T(4.0+a*(-2.0),5.0+ a*3.0));
}
};
template<typename F, typename T>
class Min {
void min(F fun1, T& v)
{
double x={10.0};
v=fun1(x);
}
};
int main()
{
double val;
Fun5<double> o5;
Fun3<decltype (o5.fun5)> o3;
Min<???,decltype (o5.fun5)> obj; //What is here?
obj(o3.fun3(o5.fun5),val);
std::cout<<"value = "<<val<<"\n";
return 0;
}
I don't know what will go to commented line.
How can I use a function object (functor) here?
I want to evaluate fun3(fun5(x))
min([](auto x){ return fun3(fun5(x)); }, val);
There's no function composition in C++ standard library (though it can be defined with some effort.)
If you really want fun, at least try lambdas. They are simple.
I'd say stay away from templates in the way you want to use them. I am assuming you want a simple happy life to focus on productive thing and I may be wrong. Pardon.
Still, I worked on your code a bit and would say that don't confuse template and macros. It looks like the case at least to me.
Note that the template actually instantiate the code and for that all you can pass is arguments to whatever types and specify those types while template instantiating.
Here is a code sample at ideone - not exactly same but to show how something can be done.
For min(fun3(fun5),val);
If you really want fun3 behavior, pass it. Dont expect the result to be passed just like it works for macro.
.
#include <iostream>
#include <cmath>
using namespace std;
typedef double (*_typeofFun1)(double&);
typedef double (*_typeofFun3)(double&, double&);
template<typename T>
T fun3(T &x1, T &x2)
{
return std::pow(x1,2.0) + std::pow(x2,2.0);
}
template<typename T, typename U>
U fun5(T t, U &a)
{
//return (T(4.0+a*(-2.0),5.0+ a*3.0));
return t(a,a);
}
template <typename T>
T fun1Param(T& arg)
{
return 2*arg;
}
template<typename F, typename T>
void min(F fun1, T& v)
{
double x={10.0};
v=fun1(x);
}
int main()
{
double val = 1.0;
double d = fun5<_typeofFun3, double> (fun3, val);
fun3<double>(d, val);
min<_typeofFun1>(fun1Param,val);
std::cout<<"value = "<<val<<"\n";
return 0;
}

More than one round bracket in function call?

I have an exercise where I need to write a function. Function scheme look like
auto add(int a){
}
I need to be able to call this function with many brackets:
add(1)(2)(3); // 6
add(1)(2)(3)(4); // 10
add(1)(2)(3)(4)(5); // 15
But I can not figure out which C++ feature I should use in this case. I heard that I should use functors but I don't know if this is the best idea in this case.
You can do it by having add return a functor, i.e., an object that implements operator(). You can write a templated version that will let the compiler deduce the type. Try it here.
template <class T>
struct adder
{
T val;
adder(T a) : val(a) {}
template <class T2>
auto operator()(T2 a) -> adder<decltype(val + a)> { return val + a; }
operator T() const { return val; }
};
template <class T>
adder<T> add(T a)
{
return a;
}
Example
In this example, T will ultimately resolve to double:
std::cout << add(1)(2.5)(3.1f)(4) << std::endl;
// T is int -----^
// T is double ------^
// T is still double -----^
// T is still double ----------^
Here is another example where T will resolve to double:
std::cout << add(1)(2.5f)(3.1)(4) << std::endl;
// T is int -----^
// T is float -------^
// T is double ------------^
// T is still double ----------^
Explicit Constructor
If you want the constructor of adder to be explicit you also have to change the return statements slightly.
template <class T>
struct adder
{
T val;
explicit adder(T a) : val(a) {}
template <class T2>
auto operator()(T2 a) -> adder<decltype(val + a)>
{
return adder<decltype(val + a)>(val + a);
}
operator T() const { return val; }
};
template <class T>
adder<T> add(T a)
{
return adder<T>(a);
}
The only solution that comes to my head is make this "add" as some class object with overloaded brackets operator, which will return new object, and then call new brackets from it, but you will need to return final value from it somehow, like some getter func.
class Adder{
private:
int value;
public:
Adder():value(0){}
Adder(int a):value(a){}
int get(){return value;}
Adder operator() (int a) {
return Adder(value+a);
}
};
But it doesn't seem as something useful, probably there is better way to accomplish what you want to get.

How to write a wrapper that keeps rapping the output?

Basically, what I want to do is to hava a wrapper on some abstract class, then have the same wrapper class wrap around the output of any member function of that class. Keep doing that so that all objects are always wrapped.
Like (presudocode)
wrap<set(1..10)> (multiply,2)
(divide,3)
(plus,5)
(inverse)
(collect first 10)
.unwrap()
All lines above except the last line outputs wrap of something. It seems to be meanling less for now, but I believe then we can apply interesting things on it like:
wrap<someClass> dat;
dat.splitIntoThreads(2)
(thingA) .clone()
(thingB) (thing1)
(thingC) (thing2)
(thingD) (thing3)
.nothing() (thing4)
.sync() .exit()
.addMerge()
Here is my code for wrap:
template<class T>
struct wrap{
wrap(){}
wrap(T b){a=b;}
template<class L,class...R>
L operator() (L(T::*f)(R...),R...r){
return a.f(r...);
}
T a;
};
int main(){
wrap<testClass> a;
a(&testClass::f,13,'a');
}
It's working (gcc, c++0x). But when I replace the 6,7th line with the following (to actually wrap the result)
wrap<L> operator() (L(T::*f)(R...),R...r){
return wrap<L>(a.f(r...));
The compiler just sais: creating pointer to member function of non-class type "int".
How can I fix this? Is there any better to do this? Inheritence is one way but since we might have variable instance in one wrap, I think it's not useful.
EDIT
Here's my test class
struct testClass{
int f(int a,char b){
return a+b;
}
};
The reason why I'm using wrap L instead of wrap T is that the return type might not always be T.
You can try something like this:
#include <iostream>
#include <type_traits>
template<class T, bool = false>
struct wrap{
template <typename... Args>
wrap(Args&&... args) : a{std::forward<Args>(args)...} {};
template<class L, class...R>
wrap<L,std::is_fundamental<L>::value> operator() (L(T::*f)(R...),R...r){
return wrap<L,std::is_fundamental<L>::value > {(a.*f)(r...)};
}
T a;
};
template<class T>
struct wrap <T,true>{
template <typename... Args>
wrap(Args&&... args) : a{std::forward<Args>(args)...} {}
template<class L, class...R>
wrap<L,std::is_fundamental<L>::value> operator() (L(*f)(T a, R...), R...r){
return wrap<L,std::is_fundamental<L>::value > {f(a, r...)};
}
T a;
};
class testClass {
int m;
public:
testClass(int _m) : m{_m}{}
int multiAdd(int x, char y) {
m += x + y;
return m;
}
};
int add(int a, char b)
{
return a+b;
}
int main(){
wrap<testClass> a{0};
std::cout << a(&testClass::multiAdd,0,'d')(add,'a').a<<std::endl;
wrap<int, true> b{3};
std::cout << b(add,'a').a<<std::endl;
}
cpp.sh/6icg
It seems the error is in your testclass definition. Please check the below example.
Also, wrap in the operator() can be returned as reference. I don't see any need to create temporaries to be used for () chaining.
template<class T>
struct wrap{
template <typename... Args>
wrap(Args&&... args) : a{std::forward<Args>(args)...} {};
template<class L, class...R>
wrap<T>& operator() (L(T::*f)(R...),R...r){
a.f(r...);
return *this; //returning reference to current wrap object.
}
T a;
};
A test class to accumulate numbers.
class testClass {
int m;
public:
testClass(int _m) : m{_m}{}
int f(int x) {
m += x;
std::cout << ' ' << m;
return m;
}
};
An usage example:
int main(){
wrap<testClass> a{0};
a(&testClass::f,13)(&testClass::f, 11)(&testClass::f,3)(&testClass::f, 21);
}
Output of sum accumulated at each step:
13 24 27 48

C++ template and ambiguous function call

Some code I have no control over has a number of overloaded functions which accepts different types
i.e.
setValue(int)
setValue(std::string)
setValue(bool)
And I have a template function which would idealy take any one of these types and pass it on to the correct setValue function.
template <class T>
do_something(T value) {
...
setValue(value);
But I get this error
error: call to member function 'SetValue' is ambiguous
Is there anything I can do to work around this problem without copy and pasting my code for each type like the writers of setValue have?
by defining you own SetValue with exact match and forwarding to the correct overload.
void setValue(int i) { setValue(static_cast<double>(i)) }
or (if you have a lot of "setValue" functions with same type) you may help the compiler to choose which overload to use like this:
void setValue(char a);
void setValue(double a);
template <typename T>
struct TypeToUseFor
{
typedef T type;
};
template <>
struct TypeToUseFor<int>
{
typedef double type;
};
template <class T>
void func(T value)
{
setValue(static_cast<typename TypeToUseFor<T>::type>(value));
// setValue(value);
}
int main() {
func(0); // int -> ?
func('0'); // exact match
func(0.0); // exect match
func(0.f); // float -> double
return 0;
}
I have no problems with:
void setValue(int a)
{
}
void setValue(std::string a)
{
}
void setValue(bool a)
{
}
template <class T>
void func(T value)
{
setValue(value);
}
int main()
{
func(5);
}
Here is my run: http://codepad.org/1wq8qd7l