Não é mais possível fazer postagens ou usar assinaturas novas da Usenet nos Grupos do Google. O conteúdo histórico continua disponível.
Dismiss

Dot operator Overloading

216 visualizações
Pular para a primeira mensagem não lida

Thiago A.

não lida,
31 de mar. de 2010, 18:36:4131/03/2010
para

Using function notation we have expressions like that:

F(G(H(X)))

Where we have to read from inside to outside. It is not so bad; this
is the normal mathematical notation.

However in some cases, I would prefer to read expression from left to
right applying the next function in the previous result.

H(x) G() F()

We can have this kind of expressions using member functions.
x.H().G().H();

In this case, each return type must have member functions for that
algorithm. But algorithms can me separated from data.
The solution that I could think about is to have an overload for
operator dot.

ReturnType operator . H (const X& x)
{
}

This operator dot would be valid only if the expression x.H() was not
defined before using member functions.

The syntax sugar would be useful in some cases.

For instance, we could write:

matrix.Rotate(pi).ReflectHor().Inverse();

instead of:

Inverse(ReflectHor(Rotate(matrix)));

Is this too much syntax sugar?
Is the dot operator overload too hard to be defined? (I know that we
can’t do this today)


Also in C++ we don’t have this kind of syntax sugar:
using x {
.Rotate(pi);
.RefelectHor();
.Inverse();
}


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Seungbeom Kim

não lida,
31 de mar. de 2010, 19:51:1831/03/2010
para
On 2010-03-31 15:36, Thiago A. wrote:
>
> However in some cases, I would prefer to read expression from left to
> right applying the next function in the previous result.
>
> H(x) G() F()

Only in the (special) case where each function takes one parameter.

Expressions could be made readable from left to right in general, for
example, with a notation that puts the function name on the right:

(w, ((x, y)f1, z)f2)f3

instead of

f3(w, f2(f1(x, y), z))

but this deviates too much from the conventional mathematical notation.

Furthermore, if an expression becomes too long and complicated
to parse at a glance, it's always a good idea to break it up
into smaller expressions and give them proper names.

> The syntax sugar would be useful in some cases.
>
> For instance, we could write:
>
> matrix.Rotate(pi).ReflectHor().Inverse();
>
> instead of:
>
> Inverse(ReflectHor(Rotate(matrix)));

This is already possible, for example, if matrix is an object of
a class that has member functions Rotate, ReflectHor, and Inverse,
and they all return the reference to *this.

This is not much different from the operator chaining:

std::cout << std::setw(8) << value << std::endl

where each function returns the reference to the stream.

> Also in C++ we don’t have this kind of syntax sugar:
> using x {
> .Rotate(pi);
> .RefelectHor();
> .Inverse();
> }

Because it can easily be written out:

x.Rotate(pi);
x.ReflectHor();
x.Inverse();

If x turns out to be a long expression you don't want to repeat,
you can create an alias:

T& x = long_expression_with(arguments);
x.Rotate(pi);
x.ReflectHor();
x.Inverse();

where T could be just written as "auto" in the next version of C++.

--
Seungbeom Kim

pfultz2

não lida,
31 de mar. de 2010, 22:36:0431/03/2010
para

> For instance, we could write:
>
> matrix.Rotate(pi).ReflectHor().Inverse();
>
> instead of:
>
> Inverse(ReflectHor(Rotate(matrix)));

You don't need to overload the dot operator to get this kind of
behaviour. You just have each function return another matrix or a
reference to a matrix like so:

class Matrix
{
public:
Matrix& Rotate(double val)
{
//Do calculations
return *this;
}

Matrix& ReflectHor()
{
//Do calculations
return *this;
}

Matrix& Inverse()
{
//Do calculations
return *this;
}
};

You could return a copy instead of reference if you have an immutable
matrix class. But now you can use your class like so:

Matrix m;
m.Rotate(3.14).ReflectHor().Inverse();

Andy Venikov

não lida,
31 de mar. de 2010, 22:36:2031/03/2010
para
Thiago A. wrote:
> Using function notation we have expressions like that:
>
> F(G(H(X)))
>
> Where we have to read from inside to outside. It is not so bad; this
> is the normal mathematical notation.
>
> However in some cases, I would prefer to read expression from left to
> right applying the next function in the previous result.
>
> H(x) G() F()
>
> We can have this kind of expressions using member functions.
> x.H().G().H();
>
> In this case, each return type must have member functions for that
> algorithm. But algorithms can me separated from data.
> The solution that I could think about is to have an overload for
> operator dot.
>
> ReturnType operator . H (const X& x)
> {
> }
>
> This operator dot would be valid only if the expression x.H() was not
> defined before using member functions.
>
> The syntax sugar would be useful in some cases.
>
> For instance, we could write:
>
> matrix.Rotate(pi).ReflectHor().Inverse();
>
> instead of:
>
> Inverse(ReflectHor(Rotate(matrix)));


You can't overload operator . ()
But in your case you don't need to.
Just have every algorithm function (like Rotate())
return a reference to a (non-local) object that defines other needed
functions, like ReflectHor()


HTH,
Andy.

Thiago A.

não lida,
31 de mar. de 2010, 23:04:2931/03/2010
para
> > However in some cases, I would prefer to read expression from left to
> > right applying the next function in the previous result.
>
> > H(x) G() F()
>
> Only in the (special) case where each function takes one parameter.
>
> Expressions could be made readable from left to right in general, for
> example, with a notation that puts the function name on the right:
>
> (w, ((x, y)f1, z)f2)f3
>
> instead of
>
> f3(w, f2(f1(x, y), z))
>
> but this deviates too much from the conventional mathematical notation.


The first argument is always the one we can put before the dot, and we
could have N arguments.

For instance, using your sample:

f3(w, f2(f1(x, y), z))

and changing names just to express the idea:

f3_DotProduct(w_vector, f2_Normalize( f1_Rotate(x_vector,
y_scalar), z_scalar))

could be written:

vector_w.f3_DotProduct(vector_x.f1_Rotate(scalar_y).f2_Normalize(scalar_z));

--

Mathias Gaunard

não lida,
1 de abr. de 2010, 10:08:4301/04/2010
para
On Mar 31, 11:36 pm, "Thiago A." <thiago.ad...@gmail.com> wrote:
> Using function notation we have expressions like that:
>
> F(G(H(X)))
>
> [...]

>
> For instance, we could write:
>
> matrix.Rotate(pi).ReflectHor().Inverse();

This works fine, but the main problem is that it is intrusive: you
need to have such functions declared as members of the returned types.
Using operator overloading, you can avoid this issue.

Consider matrix | Rotate(pi) | ReflectHor() | Inverse()
Such syntax is used by the new extension to Boost.Range.

Thiago A.

não lida,
1 de abr. de 2010, 13:16:4101/04/2010
para

> But in your case you don't need to.
> Just have every algorithm function (like Rotate())
> return a reference to a (non-local) object that defines other needed
> functions, like ReflectHor()

The problem of member-function is to repeat the same algorithm in each
class, or to have to create a non-member function and call it from
each member-function. Consequently each class must know each
algorithm. Apart of that, sometimes you cannot change the class code,
like std::vector or the type is not a class.

For instance:
2.pow(3);

int operator . pow (int a, int b) { return pow(a, b); }

Thiago A.

não lida,
1 de abr. de 2010, 13:17:1801/04/2010
para

> > Using function notation we have expressions like that:
>
> > F(G(H(X)))
>
> > [...]
>
> > For instance, we could write:
>
> > matrix.Rotate(pi).ReflectHor().Inverse();
>
> This works fine, but the main problem is that it is intrusive: you
> need to have such functions declared as members of the returned types.
> Using operator overloading, you can avoid this issue.
>
> Consider matrix | Rotate(pi) | ReflectHor() | Inverse()
> Such syntax is used by the new extension to Boost.Range.

I agree.
In the matrix sample, the operator * could be used.
But considering generic samples the math operators can be VERY
confusing.
Maybe the general idea is to create �named� operators like "pow".
2 + 2 pow 3;
However in this case we should also declare the precedence and this
also would be very confusing.

I think that the dot operator would be simpler because the precedence
is the same we use in class members.
2 + 2.pow(3)

achp

não lida,
1 de abr. de 2010, 13:17:2701/04/2010
para
On Apr 1, 2:36 am, "Thiago A." <thiago.ad...@gmail.com> wrote:
> However in some cases, I would prefer to read expression from left to
> right applying the next function in the previous result.
>
> H(x) G() F()

I don't think you can have it that way.

However, you might choose to have it this way:

apply(x, H, G, F);

where

template<class T>
T apply(T x)
{
return std::forward<T>(x);
}

template<class T, class F1, class... Fn>
auto apply(T x, F1 f1, Fn... fn) -> decltype(apply(f1(x),
std::forward<Fn>(fn)...))
{
return apply(f1(x), std::forward<Fn>(fn)...);
}

Sorry for mistakes, I have not tested it, but you probably got the
idea.

Seungbeom Kim

não lida,
1 de abr. de 2010, 17:54:4001/04/2010
para
On 2010-04-01 07:08, Mathias Gaunard wrote:
> On Mar 31, 11:36 pm, "Thiago A."<thiago.ad...@gmail.com> wrote:
>>
>> For instance, we could write:
>>
>> matrix.Rotate(pi).ReflectHor().Inverse();
>
> This works fine, but the main problem is that it is intrusive: you
> need to have such functions declared as members of the returned types.
> Using operator overloading, you can avoid this issue.

This is a valid concern. Then how about defining one function
that can call arbitrary operations:

matrix.apply(Rotate, pi).apply(ReflectHor).apply(Inverse);

> Consider matrix | Rotate(pi) | ReflectHor() | Inverse()
> Such syntax is used by the new extension to Boost.Range.

I like this syntax, too!

--
Seungbeom Kim

Kumar Anurag

não lida,
2 de abr. de 2010, 11:58:5202/04/2010
para
On Apr 2, 2:54 am, Seungbeom Kim <musip...@bawi.org> wrote:
> On 2010-04-01 07:08, Mathias Gaunard wrote:
>
> > On Mar 31, 11:36 pm, "Thiago A."<thiago.ad...@gmail.com> wrote:
>
> >> For instance, we could write:
>
> >> matrix.Rotate(pi).ReflectHor().Inverse();
>
> > This works fine, but the main problem is that it is intrusive: you
> > need to have such functions declared as members of the returned types.
> > Using operator overloading, you can avoid this issue.
>
> This is a valid concern. Then how about defining one function
> that can call arbitrary operations:
>
> matrix.apply(Rotate, pi).apply(ReflectHor).apply(Inverse);
>
> > Consider matrix | Rotate(pi) | ReflectHor() | Inverse()
> > Such syntax is used by the new extension to Boost.Range.
>
> I like this syntax, too!

{ edits: quoted sig & banner removed. please keep readers in mind when you
quote. -mod }

I have read that .(dot) operator can't be overloaded. Is it false??


--

Mark Zaytsev

não lida,
9 de abr. de 2010, 17:16:2209/04/2010
para
On Mar 31, 6:36 pm, "Thiago A." <thiago.ad...@gmail.com> wrote:
> Using function notation we have expressions like that:
>
> F(G(H(X)))
>
> Where we have to read from inside to outside. It is not so bad; this
> is the normal mathematical notation.
>
> However in some cases, I would prefer to read expression from left to
> right applying the next function in the previous result.
>
> H(x) G() F()

Why not to overload 'operator ,' ?
x, H(), G(), F()

0 nova mensagem