Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I explicitly call an exception-throwing method in C++?

Tags:

I have a simple class:

class A {  public:   bool f(int* status = nullptr) noexcept {     if (status) *status = 1;     return true;   }   void f() {     throw std::make_pair<int, bool>(1, true);   } };  int main() {   A a;   a.f(); // <- Ambiguity is here! I want to call 'void f()' } 

I want to resolve ambiguity of a method call in favour of the exception-throwing method by any means.

The rationale behind such interface:

  • To have the noexcept(true) and noexcept(false) interface,
  • To allow optionally get extra information via a pointer in the noexcept(false) variant - while the noexcept(true) variant will always pack this information inside an exception.

Is it possible at all? Suggestions for a better interface are also welcome.

like image 285
abyss.7 Avatar asked Jan 07 '18 10:01

abyss.7


People also ask

How do you throw an exception explicitly?

You can explicitly throw an exception using the C# throw or the Visual Basic Throw statement. You can also throw a caught exception again using the throw statement. It is good coding practice to add information to an exception that is re-thrown to provide more information when debugging.

What happens when Noexcept function throws?

noexcept means that a function will not throw, not that it cannot throw, and the penalty for failure to comply is calling std::terminate , not UB.

What is throw exception in C #?

Exceptions are used to indicate that an error has occurred while running the program. Exception objects that describe an error are created and then thrown with the throw keyword. The runtime then searches for the most compatible exception handler.

How do you know if a method is throwing exception?

The calculate method should check for an exception and if there is no exception, return the calculated value to the main function i.e. v1+v2 or v1-v2; Else if an exception exists then it should print the error statement and the value that is returned from the calculate method to the main method should be 0.0(Not ...


Video Answer


2 Answers

Having functions with this kind of signatures is obviously a bad design as you've found out. The real solutions are to have different names for them or to lose the default argument and were presented already in other answers.

However if you are stuck with an interface you can't change or just for the fun of it here is how you can explicitly call void f():

The trick is to use function pointer casting to resolve the ambiguity:

a.f(); // <- ambiguity is here! I want to call 'void f()'  (a.*(static_cast<void (A::*)()>(&A::f)))(); // yep... that's the syntax... yeah... 

Ok, so it works, but don't ever write code like this!

There are ways to make it more readable.

Use a pointer:

// create a method pointer: auto f_void = static_cast<void (A::*)()>(&A::f);  // the call is much much better, but still not as simple as `a.f()` (a.*f_void)(); 

Create a lambda or a free function

auto f_void = [] (A& a) {     auto f_void = static_cast<void (A::*)()>(&A::f);     (a.*f_void)(); };  // or  void f_void(A& a) {     auto f_void = static_cast<void (A::*)()>(&A::f);     (a.*f_void)(); };   f_void(a); 

I don't know if this is necessary better. The call syntax is definitely simpler, but it might be confusing as we are switching from a method call syntax to a free function call syntax.

like image 73
bolov Avatar answered Sep 19 '22 19:09

bolov


Both versions f have different meanings.

They should have two different name, as:

  • f for the throwing one, because using it means that your are confident on success, and failure would be an exception in the program.
  • try_f() or tryF() for the error-return based one, because using it means that failure of the call is an expected outcome.

Two different meanings should be reflected in the design with two different name.

like image 42
Guillaume Fouillet Avatar answered Sep 20 '22 19:09

Guillaume Fouillet