Puzzle: make new compilers understand what g++ 2.95.3 compiled

G

Guest

When language changes make old code uncompilable, that's not what is
called protection of investment.

New compilers (g++ > 3.2.3) reject classes where methods throw the
class they belong to.
gcc 2.95.3 allowed it.

What are the minimal modification, that leave the usage of the class
sound and can be compiled by newer compilers.

Thank you

( compile the following code with s.th. like g++ -g -o Exception
Exception.cpp -lstlport_gcc )

#include "iostream"

class Exception {
public:
Exception(int);
void setErrNo(int i) throw(Exception);
int errNo;

};

Exception::Exception(int e) {
errNo=e;

}

void Exception::setErrNo(int i) throw(Exception) {
auto Exception methodException(2);
errNo=i;
throw(methodException);

};

int main(char argc, char *argv[], char *env[]) {
try {
auto Exception mainException(1);
mainException.setErrNo(42);
} catch (Exception caughtException) {
std::cout << "caught caughtException:" << caughtException.errNo <<
std::endl;
}
 
K

Keith Halligan

When language changes make old code uncompilable, that's not what is
called protection of investment.

New compilers (g++ > 3.2.3) reject classes where methods throw the
class they belong to.
gcc 2.95.3 allowed it.

What are the minimal modification, that leave the usage of the class
sound and can be compiled by newer compilers.

Thank you

( compile the following code with s.th. like g++ -g -o Exception
Exception.cpp -lstlport_gcc )

#include "iostream"

class Exception {
public:
Exception(int);
void setErrNo(int i) throw(Exception);
int errNo;

};

Exception::Exception(int e) {
errNo=e;

}

void Exception::setErrNo(int i) throw(Exception) {
auto Exception methodException(2);
errNo=i;
throw(methodException);

};

int main(char argc, char *argv[], char *env[]) {
try {
auto Exception mainException(1);
mainException.setErrNo(42);
} catch (Exception caughtException) {
std::cout << "caught caughtException:" << caughtException.errNo <<
std::endl;

}

Remove the `throw(Exception)' statements from the function setErrNo.
Your catch block is trying to catch an exceptions of type Exception
and setErrNo will throw and Exception type so it will be caught
correctly.

Using gcc 3.4.6 it will compile and work fine this way.

The C++ standard states that "Classes in exception specifiers must be
complete types", so throw(Exception) is disallowed.
 
G

Guest

Thank you Keith Halligan.

To keep the information in the signatures, we now use an empty
declarative substitute, so the developer can see from the header, what
he might have to catch.

#include "iostream"

#if ( GCC_VERSION > 30000 )
# define declare_throw(Exception) throw(Exception)
#else
# define declare_throw(Exception)
#endif

class Exception {
public:
Exception(int);
void setErrNo(int i) declare_throw(Exception);
int errNo;
};

Exception::Exception(int e) {
errNo=e;
}

void Exception::setErrNo(int i) declare_throw(Exception) {
auto Exception methodException(2);
errNo=i;
throw(methodException);
};

int main(char argc, char *argv[], char *env[]) {
try {
auto Exception mainException(1);
mainException.setErrNo(42);
} catch (Exception caughtException) {
std::cout << "caught caughtException:" << caughtException.errNo <<
std::endl;
}
}
 
F

Fei Liu

Thank you Keith Halligan.

To keep the information in the signatures, we now use an empty
declarative substitute, so the developer can see from the header, what
he might have to catch.

#include "iostream"

#if ( GCC_VERSION > 30000 )
# define declare_throw(Exception) throw(Exception)
#else
# define declare_throw(Exception)
#endif

class Exception {
public:
Exception(int);
void setErrNo(int i) declare_throw(Exception);
int errNo;
};

Exception::Exception(int e) {
errNo=e;
}

void Exception::setErrNo(int i) declare_throw(Exception) {
auto Exception methodException(2);
errNo=i;
throw(methodException);
};

int main(char argc, char *argv[], char *env[]) {
try {
auto Exception mainException(1);
mainException.setErrNo(42);
} catch (Exception caughtException) {
std::cout << "caught caughtException:" << caughtException.errNo <<
std::endl;
}
}

This is a good practical solution. Did you try throw(Exception *)? Or is
that something not allowed in C++? I belive you can throw string,
integer etc. So you could throw a string message as well.
 
A

Andre Kostur

Fei Liu said:
Thank you Keith Halligan.

To keep the information in the signatures, we now use an empty
declarative substitute, so the developer can see from the header, what
he might have to catch.

#include "iostream"

#if ( GCC_VERSION > 30000 )
# define declare_throw(Exception) throw(Exception)
#else
# define declare_throw(Exception)
#endif

class Exception {
public:
Exception(int);
void setErrNo(int i) declare_throw(Exception);
int errNo;
};

Exception::Exception(int e) {
errNo=e;
}

void Exception::setErrNo(int i) declare_throw(Exception) {
auto Exception methodException(2);
errNo=i;
throw(methodException);
};

int main(char argc, char *argv[], char *env[]) {
try {
auto Exception mainException(1);
mainException.setErrNo(42);
} catch (Exception caughtException) {
std::cout << "caught caughtException:" << caughtException.errNo <<
std::endl;
}
}

This is a good practical solution. Did you try throw(Exception *)? Or is
that something not allowed in C++? I belive you can throw string,
integer etc. So you could throw a string message as well.

Be careful when throwing pointers as exceptions. Specifically, what is
the pointer going to be pointing at by the time the catch clause is
evaluated. If you've thrown a pointer to a local variable, it will be
out of scope by the time the catch clause executes.
 
P

peter koch

Thank you Keith Halligan.

To keep the information in the signatures, we now use an empty
declarative substitute, so the developer can see from the header, what
he might have to catch.

I recommend a much better solution: do not use exception
specifications. Instead have the specification in a comment:
void setErrNo(int i); // throws Exception
Exception specifications really are more of less useless and will
often make the code slower and (more important) difficult to maintain/
extend. The comment is harmless here.
I assume that you do not expect the immediate caller to catch the
exception? In that case, using return codes would seem like a better
idea.
Last, I do not understand that usage of "auto". What is it for? The
keyword is clearly superflous here.

/Peter
#include "iostream"

#if ( GCC_VERSION > 30000 )
# define declare_throw(Exception) throw(Exception)
#else
# define declare_throw(Exception)
#endif

class Exception {
public:
Exception(int);
void setErrNo(int i) declare_throw(Exception);
int errNo;

};

Exception::Exception(int e) {
errNo=e;

}

void Exception::setErrNo(int i) declare_throw(Exception) {
auto Exception methodException(2);
errNo=i;
throw(methodException);

};

int main(char argc, char *argv[], char *env[]) {
try {
auto Exception mainException(1);
mainException.setErrNo(42);
} catch (Exception caughtException) {
std::cout << "caught caughtException:" << caughtException.errNo <<
std::endl;
}



}
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top