From: Daniel Krügler on
On 29 Jul., 02:16, Lorenzo Caminiti <lorcamin...(a)gmail.com> wrote:
> Here's more background information about what I want to do and why.
>
> BACKGROUND
>
> I am programming a macro which evaluates a code expression in constant-
> correct context

Do you mean *const-correct* here?

> by executing the code from within a local function by passing the object
> `this` and other variables as `const`. For example, the
`BLOCK_INVARIANT()`
> macro can be programmed so that the following:
>
> class c {
> public:
> c(int x): x_(x) {}
>
> bool eq(int x) const { return x_ == x; };
>
> void f(int x) {
> BLOCK_INVARIANT( (const (c*)(this) (int)(x) (this_->eq(x)
> == false)) )
> }
>
> private:
> int x_;
> };
>
> Expands to:
>
> class c {
> public:
> c(int x): x_(x) {}
>
> bool eq(int x) const { return x_ == x; };
>
> void f(int x) {
> struct block_invariant {
> static void check(c const* const this_, int const& x)
> {
> if(!( this_->eq(x) == false )) { // Evaluated in
> constant-correct context because `this_` and `x` are `const`.

OK, you *mean* const-correct ;-)

> throw int(-1);
> }
> }
> };
> block_invariant::check(this, x);
> }
>
> private:
> int x_;
> };
>
> Now the compiler will generate an error if the code expression passed
> to `BLOCK_INVARIANT()` -- `this_->eq(x)` in this example -- is not
> constant-correct.
>
> However, ideally the code expression passed to `BLOCK_INVARIANT()`
> will looks the exactly the same as the code programmed within `f()`.
> Therefore, `this_->eq(x)` will ideally be `this->eq(x)`. Is there a
> way I can do this without inheriting `block_inv` from `c`? And that is
> what I need.

I can think only of one way to realize that, but it requires
a new feature of C++0x, which are lambda expressions:

A lambda expression produces a class type within the
smallest scope that contains the expression. Without any
macro, the test could be written as follows:

class c {
public:
c(int x): x_(x) {}

bool eq(int x) const { return x_ == x; };

void f(int x) {
// Macro expansion starts here
[&] {
if (!(this->eq(x) == false)) {
throw int(-1);
}
}();
// Macro expansion end here
}

private:
int x_;
};

I'm not sure whether this approach satisfies your const-
correctness stringency. Above code is always well-formed,
if the test-expression were well-formed within the same
context (which is the context of c::f in above example). Since
f() is a non-constant member function, it would also allow
for tests that call non-const functions, because those are
valid in that context.

HTH & Greetings from Bremen,

Daniel Kr�gler


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

From: Goran Pusic on
> I am programming a macro which evaluates a code expression in constant-
> correct context by executing the code from within a local function by
> passing the object `this` and other variables as `const`. For example,
> the `BLOCK_INVARIANT()` macro can be programmed so that the following:
>
> class c {
> public:
> c(int x): x_(x) {}
>
> bool eq(int x) const { return x_ == x; };
>
> void f(int x) {
> BLOCK_INVARIANT( (const (c*)(this) (int)(x) (this_->eq(x)
> == false)) )
> }
>
> private:
> int x_;
> };
>
> Expands to:
>
> class c {
> public:
> c(int x): x_(x) {}
>
> bool eq(int x) const { return x_ == x; };
>
> void f(int x) {
> struct block_invariant {
> static void check(c const* const this_, int const& x)
> {
> if(!( this_->eq(x) == false )) { // Evaluated in
> constant-correct context because `this_` and `x` are `const`.
> throw int(-1);
> }
> }
> };
> block_invariant::check(this, x);
> }
>
> private:
> int x_;
> };
>
> Now the compiler will generate an error if the code expression passed
> to `BLOCK_INVARIANT()` -- `this_->eq(x)` in this example -- is not
> constant-correct.

(You could have shown definition of BLOCK_INVARIANT)

That said, if const-correctness is your goal, then you still don't
need additional class. A const_cast (no blind C casts please, we're in
C++ ;-) ) could do, couldn't it?

What if you simply do:

#define BLOCK_INVARIANT(object_type, check, param_type, param) \
{ if (!const_cast<const object_type*>(this)->check((const param_type&)
(param))) throw -1;}

and then, in f():

BLOCK_INVARIANT(c, eq, int, x).

You can eliminate c by using another macro inside class definition
file, e.g. in c.cpp

#define BLOCK_INVARIANT_C(check, param_type, param) BLOCK_INVARIANT(c,
check, param_type, param)

By the way, that throw -1 stands out like a sore thumb. How's that
supposed to be used? When your invariant is broken, you pop up to the
top of the stack (e.g. to main) and do

catch(int i)
{
return int;
}

?

That's, frankly, worse than crashing or aborting, because you will
lose the place where crash happened. How about at least an exception
containing __FILE__, and __LINE__?

Goran.


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

From: Anthony Williams on
Lorenzo Caminiti <lorcaminiti(a)gmail.com> writes:

> Here's more background information about what I want to do and why.

Thank you, that's helpful.

> However, ideally the code expression passed to `BLOCK_INVARIANT()`
> will looks the exactly the same as the code programmed within `f()`.
> Therefore, `this_->eq(x)` will ideally be `this->eq(x)`. Is there a
> way I can do this without inheriting `block_inv` from `c`? And that is
> what I need.

No, you cannot do that. "this" refers to an instance of the current
class. Inside member functions of a local class, "this" refers to an
instance of that local class.

You can do it with a nasty (i.e. strictly undefined behaviour, but works
in practice) hack though: if your local class has no data members and no
virtual functions then you can derive the local class from the outer
class and cast your "this" pointer to be an instance of the local class:

#include <iostream>
class X
{
private:
void g() const
{
std::cout<<"g(), this="<<this<<std::endl;
}
public:
void f()
{
std::cout<<"f(), this="<<this<<std::endl;
struct local:X
{
void foo() const
{
this->g();
}
};

local const* p=static_cast<local const*>(const_cast<X
const*>(this));
p->foo();
}
};

int main()
{
X x;
x.f();
}

Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++0x thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

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

From: terminator on
On Jul 29, 4:16 am, Lorenzo Caminiti <lorcamin...(a)gmail.com> wrote:
> On Jul 27, 10:43 am, Goran Pusic <gor...(a)cse-semaphore.com> wrote:
>
>
>
> > > In my application, I need line (3) to essentially look the same as
> > > like line (1) so you can program code inside `y` members as if it were
> > > inside `x` members. A part from that, the local class `y` could look
> > > as it is needed to solve this problem -- with more member variables,
> > > member functions, etc.
>
> > The thing is, like with many newbie questions, you think that you need
> > line (3). But in fact, there's probably much more ways to achieve
> > desired end result, overall (calling g() on an instance of x is just
> > part of that result). In other words, you should consider changing
> > your question so that it tells more about what you want to do. The
> > question you asked is "can I do __this__ so that I can do __that__?".
> > But __this__ is tangential (and trivial).
>
> I want to program code inside `y` members as if it were inside `x`
> members. This is my only requirement.
>
> Here's more background information about what I want to do and why.
>
> BACKGROUND
>
> I am programming a macro which evaluates a code expression in constant-
> correct context by executing the code from within a local function by
> passing the object `this` and other variables as `const`. For example,
> the `BLOCK_INVARIANT()` macro can be programmed so that the following:
>
> class c {
> public:
> c(int x): x_(x) {}
>
> bool eq(int x) const { return x_ == x; };
>
> void f(int x) {
> BLOCK_INVARIANT( (const (c*)(this) (int)(x) (this_->eq(x)
> == false)) )
> }
>
> private:
> int x_;
> };
>
> Expands to:
>
> class c {
> public:
> c(int x): x_(x) {}
>
> bool eq(int x) const { return x_ == x; };
>
> void f(int x) {
> struct block_invariant {
> static void check(c const* const this_, int const& x)
> {
> if(!( this_->eq(x) == false )) { // Evaluated in
> constant-correct context because `this_` and `x` are `const`.
> throw int(-1);
> }
> }
> };
> block_invariant::check(this, x);
> }
>
> private:
> int x_;
> };
>
> Now the compiler will generate an error if the code expression passed
> to `BLOCK_INVARIANT()` -- `this_->eq(x)` in this example -- is not
> constant-correct.
>
> However, ideally the code expression passed to `BLOCK_INVARIANT()`
> will looks the exactly the same as the code programmed within `f()`.
> Therefore, `this_->eq(x)` will ideally be `this->eq(x)`. Is there a
> way I can do this without inheriting `block_inv` from `c`? And that is
> what I need.
>
> REPLIES
>
> For example, thank you for the following suggestions but they do not
> work because:
>
> On Jul 27, 10:43 am, Daniel Kr�gler <daniel.krueg...(a)googlemail.com>
> wrote:
>
>
>
>
>
> > class x { // outer class
> > public:
> > void g() {}
>
> > void f() {
> > this->g(); // (1)
>
> > struct y { // local class, no inheritance
> > x* that; // References an object of the outer class
> > y(x* super): that(super) {} // (2)
> > void h() {
> > that->g(); // (3)
> > }
> > };
> > y(this).h();
> > }
> > };
>
> Line (3) does not look the same as line (1). In other words, this
> solution does not work because I would use `that` inside `y` members
> and `this` inside `x` members so line (1) and (3) look different from
> each other.
>
> On Jul 27, 10:44 am, Anthony Williams <anthony....(a)gmail.com> wrote:
>
>
>
>
>
> > #include <iostream>
> > class X
> > {
> > private:
> > void g()
> > {
> > std::cout<<"g(), this="<<this<<std::endl;
> > }
> > public:
> > void f()
> > {
> > std::cout<<"f(), this="<<this<<std::endl;
> > struct local
> > {
> > X* self;
> > local(X* self_):
> > self(self_)
> > {}
>
> > void foo()
> > {
> > self->g();
> > }
> > };
>
> > local y(this);
> > y.foo();
> > }
>
> > };
>
> Similarly, this does not work because `self->g()` from within the
> local function looks different from `this->g()` from within the non-
> local function.
>
>

if 'y' is going to be somewhat an interface to x(say a java inner
class) then I can imagine no other/better solution that D.krugler
suggests.Ofcourse you can explicitly cast the 'x' object, but you
might need to wrap the cast in a function and neglecting the risk of
casting error the overhead wo`nt be any diffrent:

class Cy:x{
//no member objects
....
};

static Cy& y(x* const px){
return reinterpret_cast<Cy&>(*px);//cuation:very tricky!!!
};

regards,
FM.


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

From: Lorenzo Caminiti on
On Jul 29, 11:06 am, Daniel Kr�gler <daniel.krueg...(a)googlemail.com>
wrote:
> I can think only of one way to realize that, but it requires
> a new feature of C++0x, which are lambda expressions:
>
> A lambda expression produces a class type within the
> smallest scope that contains the expression. Without any
> macro, the test could be written as follows:
>
> class c {
> public:
> c(int x): x_(x) {}
>
> bool eq(int x) const { return x_ == x; };
>
> void f(int x) {
> // Macro expansion starts here
> [&] {
> if (!(this->eq(x) == false)) {
> throw int(-1);
> }
> }();
> // Macro expansion end here
> }
>
> private:
> int x_;
> };
>
> I'm not sure whether this approach satisfies your const-
> correctness stringency. Above code is always well-formed,
> if the test-expression were well-formed within the same
> context (which is the context of c::f in above example). Since
> f() is a non-constant member function, it would also allow
> for tests that call non-const functions, because those are
> valid in that context.

Yes, C++0x lambdas might help in this case but I cannot use C++0x
features :( I must only use the current C++ standard.

--
Lorenzo


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