![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Darren New
Subject: Saw a weird C++ construct I'm not sure I understand...
Date: 20 Aug 2008 12:23:50
Message: <48ac4516@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
I saw a bit of a note describing how to use an "assert" and a "check"
call in some C++. "Assert" would exit the program if it failed, and
"check" would let the program continue after logging in order to look
for more failures.
But the invocation was along the lines of
assert(x < 10) <<
"The value x is " << x << " but that's too small";
The only way I can see this working is if assert returns either a
subclass with operator<< defined to do nothing, or with operator<<
defined to log something. In the latter case, the destructor would exit
the program? Would that work?
I think to figure out C++, I need to figure out where all the invisible
method invocations are that the compiler inserts for you. That would
seem to be my biggest stumbling block right now.
--
Darren New / San Diego, CA, USA (PST)
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Fredrik Eriksson
Subject: Re: Saw a weird C++ construct I'm not sure I understand...
Date: 20 Aug 2008 12:34:08
Message: <op.uf61m5qe7bxctx@e6600>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On Wed, 20 Aug 2008 18:23:49 +0200, Darren New <dne### [at] san rr com> wrote:
> I saw a bit of a note describing how to use an "assert" and a "check"
> call in some C++. "Assert" would exit the program if it failed, and
> "check" would let the program continue after logging in order to look
> for more failures.
>
> But the invocation was along the lines of
>
> assert(x < 10) <<
> "The value x is " << x << " but that's too small";
>
> The only way I can see this working is if assert returns either a
> subclass with operator<< defined to do nothing, or with operator<<
> defined to log something. In the latter case, the destructor would exit
> the program? Would that work?
I do not see why it would not.
--
FE
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Warp
Subject: Re: Saw a weird C++ construct I'm not sure I understand...
Date: 20 Aug 2008 15:57:37
Message: <48ac7730@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> I saw a bit of a note describing how to use an "assert" and a "check"
> call in some C++. "Assert" would exit the program if it failed, and
> "check" would let the program continue after logging in order to look
> for more failures.
> But the invocation was along the lines of
> assert(x < 10) <<
> "The value x is " << x << " but that's too small";
That's a rather obscure, although clever way of printing error information
in case of assertion failure.
It's actually not obvious how it's implemented, but at least this would
work:
//------------------------------------------------------------------------
#include <iostream>
#include <cstdlib>
class DataOutput
{
const bool doExit;
public:
DataOutput(bool e): doExit(e) {}
~DataOutput()
{
if(doExit)
{
std::cerr << std::endl;
std::exit(1);
}
}
template<typename T>
DataOutput& operator<<(const T& data)
{
if(doExit) std::cerr << data;
return *this;
}
};
#define assert(cond) ((!(cond)) ? \
(DataOutput(true) << __FILE__ << " " << __LINE__ \
<< ": Assertion (" << #cond << ") failed. ") : \
DataOutput(false))
//------------------------------------------------------------------------
The only problem I see with this is that you can't compile this in a
way that completely drops out the operator<< calls and its parameters.
The operator<< calls are *always* performed, even if no assertion failure
happens, and there's no way of compiling the program so that the compiler
would drop those calls.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Darren New
Subject: Re: Saw a weird C++ construct I'm not sure I understand...
Date: 20 Aug 2008 17:11:41
Message: <48ac888d$1@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> That's a rather obscure, although clever way of printing error information
> in case of assertion failure.
That was my first impression.
> The only problem I see with this is that you can't compile this in a
> way that completely drops out the operator<< calls and its parameters.
Huh. I see what you're doing there. That too was my first thought.
(Indeed, it took me a couple minutes to even figure out how it would
exit *after* printing stuff if the assertion failed. But then I'm not a
C++ kind of person.)
I thought it might even have been the point that the operator<<
parameters get evaluated anyway, as in "don't break the code by turning
off the debugging", for parameters that might accidentally have a
side-effect.
--
Darren New / San Diego, CA, USA (PST)
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Warp
Subject: Re: Saw a weird C++ construct I'm not sure I understand...
Date: 20 Aug 2008 18:34:01
Message: <48ac9bd9@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> (Indeed, it took me a couple minutes to even figure out how it would
> exit *after* printing stuff if the assertion failed. But then I'm not a
> C++ kind of person.)
Yes, the lifetime of the temporary object created by the assert() macro
may not be completely trivial to understand.
This is a very simplified version of the situation:
//-------------------------------------------------------------------------
class Test
{
public:
Test() { std::cout << "constructor\n"; }
~Test() { std::cout << "destructor\n"; }
Test& foo(int i)
{
std::cout << i << std::endl;
return *this;
}
};
int main()
{
std::cout << "Before\n";
Test().foo(1).foo(2).foo(3); // *
std::cout << "After\n";
}
//-------------------------------------------------------------------------
The line marked with * above creates a nameless temporary instance of
the class Test. Obviously it's constructed at that location. However,
where is it destroyed? Is it destroyed before or after the "After"
printing line? If it's destroyed before, is it valid to repeatedly call
its foo() function, which returns a reference to itself?
We get an answer by running the program. It prints:
Before
constructor
1
2
3
destructor
After
This starts being slightly advanced C++, and thus not for the feint
of heart.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Darren New
Subject: Re: Saw a weird C++ construct I'm not sure I understand...
Date: 20 Aug 2008 18:58:50
Message: <48aca1aa$1@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> This starts being slightly advanced C++, and thus not for the feint
> of heart.
Do you know of a good tutorial that talks about (in relatively simple
language, i.e. not the official standard) where the constructor,
destructor, assignment operator, and copy constructor are called?
Something specific and concrete, rather than "here's how you write one"?
Basically, if I understand the rules of a language, it's usually easy
for me to understand how to use it. If you tell me only how to use it, I
usually have a hard time deducing the rules in complex cases.
Is there a list of "here's where we insert invisible invocations of
instance methods" kind of thing around that you know of?
--
Darren New / San Diego, CA, USA (PST)
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Warp
Subject: Re: Saw a weird C++ construct I'm not sure I understand...
Date: 20 Aug 2008 19:20:15
Message: <48aca6af@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Is there a list of "here's where we insert invisible invocations of
> instance methods" kind of thing around that you know of?
Sorry, I can't say I know.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Nicolas Alvarez
Subject: Re: Saw a weird C++ construct I'm not sure I understand...
Date: 20 Aug 2008 22:19:06
Message: <48acd09a@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New wrote:
> assert(x < 10) <<
> "The value x is " << x << " but that's too small";
>
> The only way I can see this working is if assert returns either a
> subclass with operator<< defined to do nothing, or with operator<<
> defined to log something. In the latter case, the destructor would exit
> the program? Would that work?
There is also the chance that assert is a macro making god knows what
hackish stuff :)
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |