Pointer to operator for builtin types

  • Thread starter =?iso-8859-1?q?Erik_Wikstr=F6m?=
  • Start date
?

=?iso-8859-1?q?Erik_Wikstr=F6m?=

Is there some way to get a function-pointer to the operators of the
builtin types? In the following example I have a generic function which
applies an operator on two values, however it does not work on builtin
types, is there a way to make this work?

struct Test
{
int i;
Test(int i_) : i(i_) { }
Test operator+(Test& t) { return Test(i + t.i); }
Test operator-(Test& t) { return Test(i - t.i); }
operator int() { return i; }
};

template<class T>
T operate(T& t1, T& t2, T (T::*func)(T&))
{
return (t1.*func)(t2);
}


int main() {
Test test1(1);
Test test2(2);
Test test3 = operate(test1, test2, &Test::eek:perator+);
Test test4 = operate(test1, test2, &Test::eek:perator-);

/*
int i1 = 1;
int i2 = 2;
int i3 = operate(i1, i2, ???);
int i4 = operate(i1, i2, ???)
*/
}
 
J

John Carson

Erik Wikström said:
Is there some way to get a function-pointer to the operators of the
builtin types?
No.

In the following example I have a generic function
which applies an operator on two values, however it does not work on
builtin types, is there a way to make this work?
struct Test
{
int i;
Test(int i_) : i(i_) { }
Test operator+(Test& t) { return Test(i + t.i); }
Test operator-(Test& t) { return Test(i - t.i); }
operator int() { return i; }
};
template<class T>
T operate(T& t1, T& t2, T (T::*func)(T&))
{
return (t1.*func)(t2);
}


int main() {
Test test1(1);
Test test2(2);
Test test3 = operate(test1, test2, &Test::eek:perator+);
Test test4 = operate(test1, test2, &Test::eek:perator-);

/*
int i1 = 1;
int i2 = 2;
int i3 = operate(i1, i2, ???);
int i4 = operate(i1, i2, ???)
*/
}

Why do you want to call operator+? Why not just use +. This works for both
built-in and class objects. The trick is to make class objects work like
built-in ones, not the reverse.
 
O

Ondra Holub

Erik Wikström napsal:
Is there some way to get a function-pointer to the operators of the
builtin types? In the following example I have a generic function which
applies an operator on two values, however it does not work on builtin
types, is there a way to make this work?

struct Test
{
int i;
Test(int i_) : i(i_) { }
Test operator+(Test& t) { return Test(i + t.i); }
Test operator-(Test& t) { return Test(i - t.i); }
operator int() { return i; }
};

template<class T>
T operate(T& t1, T& t2, T (T::*func)(T&))
{
return (t1.*func)(t2);
}


int main() {
Test test1(1);
Test test2(2);
Test test3 = operate(test1, test2, &Test::eek:perator+);
Test test4 = operate(test1, test2, &Test::eek:perator-);

/*
int i1 = 1;
int i2 = 2;
int i3 = operate(i1, i2, ???);
int i4 = operate(i1, i2, ???)
*/
}

AFAIK you cannot get pointer to operator+ for built-in types. But you
can wrap such type in some class:

#include <iostream>

struct Test
{
int i;
Test(int i_) : i(i_)
{ }
Test operator+(const Test& t)
{
return Test(i + t.i);
}
Test operator-(const Test& t)
{
return Test(i - t.i);
}
operator int()
{
return i;
}

};

template<typename T>
class WrapType
{
public:
WrapType(const T& data)
: data_(data)
{
}

T operator+(const T& value)
{
return data_ + value;
}

T operator-(const T& value)
{
return data_ - value;
}

private:
T data_;
};

template<typename T, typename U>
T operate(const T& t1, const T& t2, T (U::*func)(const T&))
{
return (U(t1).*func)(t2);
}

int main()
{
Test test1(1);
Test test2(2);
Test test3 = operate(test1, test2, &Test::eek:perator+);
Test test4 = operate(test1, test2, &Test::eek:perator-);

int i1 = 1;
int i2 = 2;
int i3 = operate(i1, i2, &WrapType<int>::eek:perator+);
int i4 = operate(i1, i2, &WrapType<int>::eek:perator-);

std::cout << i3 << " " << i4 << "\n";
}

If you need to call operate from some other template, there is no
problem to use WrapType always:

Test test3 = operate(test1, test2, &Wrap<Test>::eek:perator+);

Of course, you would need to define also other operators in a WrapType
template.
 
?

=?iso-8859-1?q?Erik_Wikstr=F6m?=

Why do you want to call operator+? Why not just use +. This works for both
built-in and class objects. The trick is to make class objects work like
built-in ones, not the reverse.


Because then I can have a generic function which can operate on any
type performing common operations,such as adding all elements in two
vectors/lists/whatever, and if I instead want another operation
performed I just change the function-pointer passed to the function. So
I can easily add, multiply or whatever.

I suppose that I could use functors, but then I would have to write a
functor for each operation I'd like to perform, which is a bit more
hassle than I'd like. Lambda-function would also have worked I guess.
 
O

Ondra Holub

Erik Wikström napsal:
Because then I can have a generic function which can operate on any
type performing common operations,such as adding all elements in two
vectors/lists/whatever, and if I instead want another operation
performed I just change the function-pointer passed to the function. So
I can easily add, multiply or whatever.

I suppose that I could use functors, but then I would have to write a
functor for each operation I'd like to perform, which is a bit more
hassle than I'd like. Lambda-function would also have worked I guess.

You do not have to write functors for all operations, they are already
written. You can redefine operate this way:

template<typename T, typename F>
T operate2(const T& t1, const T& t2, const F& f)
{
return f(t1, t2);
}

And then use it so:

int i5 = operate2(i1, i2, std::plus<int>());

Test test5 = operate2(test1, test2, std::plus<Test>());

One more headeris necessary: #include <functional>
 
J

John Carson

Erik Wikström said:
Because then I can have a generic function which can operate on any
type performing common operations,such as adding all elements in two
vectors/lists/whatever, and if I instead want another operation
performed I just change the function-pointer passed to the function.
So
I can easily add, multiply or whatever.

I suppose that I could use functors, but then I would have to write a
functor for each operation I'd like to perform, which is a bit more
hassle than I'd like. Lambda-function would also have worked I guess.


Have a look at the function objects available in the functional header.
These include templates for plus, minus and various other things.
 
?

=?iso-8859-1?q?Erik_Wikstr=F6m?=

Erik Wikström napsal:




You do not have to write functors for all operations, they are already
written. You can redefine operate this way:

template<typename T, typename F>
T operate2(const T& t1, const T& t2, const F& f)
{
return f(t1, t2);

}

And then use it so:

int i5 = operate2(i1, i2, std::plus<int>());

Test test5 = operate2(test1, test2, std::plus<Test>());

One more headeris necessary: #include <functional>

Thank you, and John Carson, this solves my problem quite nicely.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top