This arose because I had a try clause that only enclosed a while loop, and I
thought I'd save my code from being tabbed in one more time, so I changed:
try {
while {
/* sad code, indented more than should be necessary */
}
}
to:
try while {
/* happy code */
}
But that's when the compiler gave me the error about try requiring a
compound statement block. Anyone have an explanation for this? Thanks.
Rich
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Type& operator[](int idx)
{
if (Reading())
// some specific code
else
// some other specific code
return Something;
}
My aim is to control if I am reading uninitialized elements of a vector and
my code must be supported by different compilers and different platforms.
Thanks for your answers.
Bernard Tatin
---
You cannot. If you really need to know this, then you must have
operator[] return a proxy class. Give this class an assignment
operator from Type, and a conversion operator to Type, and you
will then be able to handle the reading and writing cases.
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
But, maybe it has to do with some 'compatibility' with the macro-implemented
versions of exceptions by compilervendors before this was in the standard.
ML
| If I overload operator[] how can I detect - in a standard way - if I am
| writing or reading a value ?
You may have to use a proxy class -- see D&E section 3.7.1 for an
illustrative example.
|
| Type& operator[](int idx)
| {
| if (Reading())
| // some specific code
| else
| // some other specific code
| return Something;
| }
|
| My aim is to control if I am reading uninitialized elements of a vector and
| my code must be supported by different compilers and different platforms.
There is no portable way to know wheter an object is "properly"
initialized unless you make use of specific idiom such as Faillible<T>
classes.
--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr
The solution is to use a "proxy" object that you return instead of Type.
You can then specify the "write" behavior in the assignment operator
of the proxy, and the "read" behavior in a conversion operator
to Type. Something like this:
template <class Type>
struct Proxy {
Proxy(Type* t) : ptr(t) { }
Proxy& operator=(const Type& t) { /* code for write */ }
operator Type() { /* code for read */ }
protected:
Type* ptr;
};
Proxy operator[](int idx) {
return Proxy(array_start_ptr + idx);
}
Cheers,
Jeremy
>Richard Burkert <rrbu...@hotmail.com> wrote in message
>news:7tgjbj$42h$1...@newsmonger.rutgers.edu...
>> My compiler told me recently that try requires a compound statement block,
>> rather than allowing the programmer to choose between a simple statement or
>> a compound one. I wonder why this is, because it seems to go against the
>> convention of most other C++ statements.
>>
>Yes I wonder too, let's wait for Bjarne ...
>But, maybe it has to do with some 'compatibility' with the macro-implemented
>versions of exceptions by compilervendors before this was in the standard.
No, it is a syntax issue. Suppose braces were not required:
try
try
foo();
catch(T t) { ... }
catch(U u) { ... }
...
A "catch" must be associated with some "try". In my example, I want
the second catch to be associated with the first try, as indicated
by the indentation. But since multiple catch blocks are allowed for
a try, the compiler would have to associate every catch with the
nearest try.
Instead of having special disambiguating rules as with if-else, C++
uses the simpler rule of requiring full sets of braces for try-catch.
There is never any ambiguity, and you won't be mislead by
indentation. Just follow the braces.
--
Steve Clamage, stephen...@sun.com
The conventional (and portable) way is to have operator[] return a
proxy<Type> instead of a Type&. You then use member functions of
proxy<Type> to detect whether the result of operator[] is being used as an
lvalue or an rvalue.
You can find lots of details in Item 30 of my "More Effective C++", which
is devoted to the ins and outs of this particular technique. I'm sure
other books discuss it, too, but I'm not familair with which ones right off
the top of my head.
Scott
--
Scott Meyers, Ph.D. sme...@aristeia.com
Software Development Consultant http://www.aristeia.com/
Visit http://meyerscd.awl.com/ to demo the Effective C++ CD
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
> > My compiler told me recently that try requires a compound statement
> > block, rather than allowing the programmer to choose between a
> > simple statement or a compound one. I wonder why this is, because
> > it seems to go against the convention of most other C++ statements.
> Yes I wonder too, let's wait for Bjarne ...
> But, maybe it has to do with some 'compatibility' with the
> macro-implemented versions of exceptions by compilervendors before
> this was in the standard.
Or maybe it has to do with not repeating past errors.
--
James Kanze mailto:James...@dresdner-bank.com
Conseils en informatique orientée objet/
Beratung in objekt orientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
Sent via Deja.com http://www.deja.com/
Before you buy.
I remember that I read somewhere in one of Bjarne's books that
there wouldn't have been a syntactical problem skipping the compound
statement blocks. This was done just be sure everyone sees it's a
try/catch.
I suppouse you should try D&E first, if you want to find the original
statement.
Schobi
The D&E says that the syntax for exception handling was designed so
verbose to "save support staff from confused users". We should call the
AT&T C++ support :-)
I am also wondering whether this issue came up in the standardization
process. It appears that a trivial enhancement to the grammar will allow
simple statement to be allowed as a try 'block'.
--
Biju Thomas
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
> If I overload operator[] how can I detect - in a standard way - if I am
> writing or reading a value ?
> Type& operator[](int idx)
> {
> if (Reading())
> // some specific code
> else
> // some other specific code
> return Something;
> }
Use a proxy class, something like
class Vector {
public:
Type* m_data;
class Proxy {
Type& m_value;
Proxy(Type& value) : m_value(value) {
}
Proxy& operator=(const Type& rhs) {
// Writing specific code
m_value = rhs;
return *this;
}
operator Type() const {
// Reading specific code
return m_value;
}
};
Proxy operator[](int i) {
return Proxy(m_data[i]);
}
};
--
Regards,
Daniel Parker danielp@no_spam.nshima.com
That is not possible, but with a lot of effort you might
achieve something that does what you want.
Here is some code to get you started, you'll need to
write more Index<> operators when needed and add a special
case check for self assignment here and there (I am lazy).
#include <iostream>
template<class T>
class Index {
T& t_;
int index_;
public:
Index(T& t, int idx) : t_(t), index_(idx) { }
Index& operator=(const Index& t) { t_.write(index_, t.read()); return *this; }
Index& operator=(const T& t) { t_.write(index_, t); return *this; }
const T& read(void) const { return t_.read(index_); }
int index(void) const { return index_; }
};
class A {
public:
Index<A> operator[](int idx) { return Index<A>(*this, idx); }
const Index<A> operator[](int idx) const { return Index<A>(*const_cast<A*>(this), idx); }
A& operator=(const Index<A>& ai) { *this = ai.read(); return *this; }
// Reading:
const A& read(int idx) const {
cout << "Reading from to A[" << idx << "]" << endl;
return *this; // fix this
}
// Writing:
void write(int idx, const A& a) {
cout << "Writing to A[" << idx << "]" << endl;
// put code here
return;
}
};
int main(void)
{
A a1;
const A& a2(a1);
a1[0] = a2;
a1 = a2[1];
a1 = a1[2] = a1[3];
}
Outputs:
Writing to A[0]
Reading from to A[1]
Reading from to A[3]
Writing to A[2]
Reading from to A[2]
Carlo Wood
>
>Richard Burkert <rrbu...@hotmail.com> wrote in message
>news:7tgjbj$42h$1...@newsmonger.rutgers.edu...
>> My compiler told me recently that try requires a compound statement block,
>> rather than allowing the programmer to choose between a simple statement
>or
>> a compound one. I wonder why this is, because it seems to go against the
>> convention of most other C++ statements.
>>
>Yes I wonder too, let's wait for Bjarne ...
>
>But, maybe it has to do with some 'compatibility' with the macro-implemented
>versions of exceptions by compilervendors before this was in the standard.
>
>ML
>
I would guess that the implementation needed a scope
to take care of constructing and destructing exception objects
plus any other objects in the "statement".
Ken Walter
Remove -zamboni to reply
All the above is hearsay and the opinion of no one in particular
>But that's when the compiler gave me the error about try requiring a
>compound statement block. Anyone have an explanation for this? Thanks.
The idea is to avoid the ambiguity that would otherwise arise in
cases such as
try try f(); catch (e1) { } catch (e2) { } catch (e3) { }
Without the requirement that "try" be followed by a compound statement,
there is no way to tell which catch clauses go with which try blocks.
--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark
---
> No, it is a syntax issue. Suppose braces were not required:
>
> try
> try
> foo();
> catch(T t) { ... }
> catch(U u) { ... }
> ...
>
> A "catch" must be associated with some "try". In my example, I want
> the second catch to be associated with the first try, as indicated
> by the indentation. But since multiple catch blocks are allowed for
> a try, the compiler would have to associate every catch with the
> nearest try.
>
> Instead of having special disambiguating rules as with if-else,
And it's _much_ worse than else, as there is no
if (x)
instr1
else
instr2
else
instr3
construct in C++, but you have the equivalent w/ exceptions.
--
Valentin Bonnard
>If I overload operator[] how can I detect - in a standard way - if I am
>writing or reading a value ?
>
>Type& operator[](int idx)
>{
> if (Reading())
> // some specific code
> else
> // some other specific code
> return Something;
>}
>
>My aim is to control if I am reading uninitialized elements of a vector and
>my code must be supported by different compilers and different platforms.
>
>Thanks for your answers.
Write a proxy class around your type and have it call the
functions you want for:
<code>
template <typename T>
struct Wrapper
{
Wrapper(int index,Vector* vec)
:index(index),
vec(vec)
{ ; }
T& operator = (const T&)
{ return vec->write(index); }
operator T& ()
{ return vec->read(index); }
private:
int index;
Vector* vec;
};
Type& Vector::operator[](int i)
{
return Wrapper(i,this);
}
</code>
I leave the considerations of in what scope to put Wrapper and
etc to you.
HTH,
Luis Coelho.
C++ Programming Language, 3rd Ed. by B. Stroustrup. My exercise answers at:
http://www.geocities.com/SiliconValley/Way/3972/index.html
Don't 'tell' which, in that case; 'assert' which instead.
I can't claim to be a formal grammer expert, but is your example really
more complicated than the situation before the C grammer was formalised
and
expressions such as
if(cond1)
if(cond2)
statement(1);
else
statement(2);
or
cond1 ? cond2 ? expression1 : expression2 : expression3;
cond1 ? cond2 : cond3 ? expression1 : expression2;
or
lvalue = value1 = value2;
or
int InClosureOf1stQuadrant = positive_p(x) || zero_p(x) &&
positive_p(y) || zero_p(y);
were considered.
Decisions were made about how things should associate etc, and I assume
in most cases that which was chosen was "that which seems most obvious
or has the easiest grammer"
Could the grammer not have asserted that the catches always correcpond
to
the innermost try (innermost such that there are enough catches left for
the outer ones)?
Could it instead not have asserted that the final catch block should be
followed by a semicolon?
I'm convinced that there is always more than one way to do things, and
that there exist similar grammers which assert that try need not take a
block.
I'm no saying it's wrong, I'm trying to be completely disinterested.
(If anything I prefer blocks, but that's irrelevant...)
Phil
--
Phil Carmody
Not speaking for or on behalf of Nokia Telecommunications
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
/* Remove NOSPAM from reply-to address to mail me */
Actually there is quite a lot of syntactic sugar in C++ exception
syntax. You actually do not need the keyword try but it increased
programmers comfort factor so it is there (and required). I suspect
that the use of 'compound statements' is similar.
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
I would expect it to bind with the most previous 'try', a la 'if/else':
if (t1) if (t2) f(); else if (e1) {} else if (e2) {} else if (e3) {}
After all, a series of catch blocks is semantically similar to a
series of else-ifs (with a final 'catch(...)' acting like a final
'else').
Or, to make it more visual:
try
try
f();
catch (e1)
{
}
catch (e2)
{
}
catch (e3)
{
}
...which is missing a catch for the first try.
But there is no compelling reason why a brace-enclosed block is
necessary for try/catch statement syntax, other than it makes it
less likely to code nested try/catch blocks incorrectly (and how
common are those?).
If the syntax was relaxed a little, "simple" try/catch groups would
be legal:
try
Foo::action();
catch (Foo::Exception e)
cleanup(e);
catch (...)
giveUp();
-- David R. Tribble, da...@tribble.com, http://www.david.tribble.com --
It's redundant philosophically (not in Standard C++). From a practical
standpoint it's made quite clear that settling "on a rather verbose
syntax using three keywords and lots of brackets" was better than
being "overly clever and/or confusing" since w/o it it was found
"so difficult to explain".
- Greg
--
Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
Producers of Comeau C/C++ 4.2.38 -- NOTE 4.2.42 BETAS NOW AVAILABLE
Email: com...@comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
*** WEB: http://www.comeaucomputing.com ***
But if you look closely, the "else" keyword is redundant as well;
you could simply define "if (condition) then-statement else-statement"
and in case there's no "else" wanted, the else-statement would be
an empty statement (";" or "{}").
Also, the braces on function blocks are redundant - one could
simply state that a statement (other than empty ";") must follow
the declaration (and then, if going consistent with variables
and requiring "extern" for a non-definition, even the ";" empty
statement could be allowed).
So without any redundancy, one would f.ex. get
if (i>j) if (j>k) j=k; ; j=i;
int max(int i, int j) if (i>j) return i; return j;
(the last works because the if statement includes the
then and else statements)
BTW, prefix "while" is redundant as well, since
"while(condition)" can be replaced by "for(;condition;)".
And if we rule out prefix "while", the "do" becomes
redundant as well - "while" would just apply to the
previous statement:
cin >> n; while (n<0); // do { cin >> n; } while (n<0);
However, we are now getting into a completely different
language ;-)
--
Martin Fabian http://www.s2.chalmers.se/~fabian/
--
"Cheer up. It may never happen" (Edina Monsoon)
/* Remove NOSPAM from reply-to address to mail me */