Author Topic: C++ issue with push-tag and friend classes  (Read 2446 times)

rowbearto

  • Senior Community Member
  • Posts: 2335
  • Hero Points: 132
C++ issue with push-tag and friend classes
« on: April 10, 2019, 01:01:04 AM »
Look for "friendissue.tar.gz" on support.

See README file for instructions to reproduce.

23.0.1.2, hotfix 2, Linux x64, CentOs 7.2.

Reproduces with a clean config.
« Last Edit: April 10, 2019, 01:27:25 AM by rowbearto »

Dennis

  • Senior Community Member
  • Posts: 3961
  • Hero Points: 517
Re: C++ issue with push-tag and friend classes
« Reply #1 on: June 06, 2019, 06:04:14 PM »
Reproduced.  This one might not be hot fixable, but I will put in a fix for v24.

[aside]
Some of us old programmers remember Dijkstra's famous 1968 paper "Go To Statement Considered Harmful".  Way, way back, when I started working with C++, I felt like the world needed a paper entitled "Friends Considered Harmful".  Not a critique of the famous TV sitcom, but simply a commentary of the messy nature of friend statements, and perhaps a bit of a pun on the general anti-social nature of many programmers, including myself.

rowbearto

  • Senior Community Member
  • Posts: 2335
  • Hero Points: 132
Re: C++ issue with push-tag and friend classes
« Reply #2 on: June 06, 2019, 07:19:53 PM »
Thanks!

I have found that when I have a few classes that are very tightly coupled that I can use friend for just those classes to access some "private" like stuff that I don't want the public interface to expose. Otherwise if class1 needs something from class2 that normal clients don't need if I make a public interface then every client can get to it (when I only want class2 to access it), which is undesirable. If you know a better way...

Similarly the advice on "goto considered harmful" in my opinion is not always so great. Especially for C (not C++ which has RAII), when you want to clean up resources. Google Linus Torvalds view on "goto" and other folks opinions on this. For example:

Code: [Select]
void myfunc()
{
  FILE *fin1=fopen("myfile", "r");
  do a bunch of stuff
  if (encounter error)
    goto closeFile1;
  FILE *fin2 = fopen("myfile2", "r");
  do a bunch of stuff2
  if (encounter error)
   goto closefile2;
  do a bunch of stuff3
closeFile2:
  fclose(fin2);
closeFile1:
  fclose(fin1);
}

This could be accomplished without gotos, but then you will have lots of different indenting levels which makes the code much less readable in my opinion.

See: https://koblents.com/Ches/Links/Month-Mar-2013/20-Using-Goto-in-Linux-Kernel-Code/
« Last Edit: June 06, 2019, 08:22:18 PM by rowbearto »

Dennis

  • Senior Community Member
  • Posts: 3961
  • Hero Points: 517
Re: C++ issue with push-tag and friend classes
« Reply #3 on: June 06, 2019, 10:20:02 PM »
The issue with 'friend' will be fixed in v24.  Thanks for the that code sample.

rowbearto

  • Senior Community Member
  • Posts: 2335
  • Hero Points: 132
Re: C++ issue with push-tag and friend classes
« Reply #4 on: June 07, 2019, 12:06:56 AM »
Thanks Dennis!

Graeme

  • Senior Community Member
  • Posts: 2796
  • Hero Points: 347
Re: C++ issue with push-tag and friend classes
« Reply #5 on: June 07, 2019, 08:43:20 AM »
Similarly the advice on "goto considered harmful" in my opinion is not always so great. Especially for C (not C++ which has RAII), when you want to clean up resources. Google Linus Torvalds view on "goto" and other folks opinions on this.

I use goto freely in C and C++, if the flow of the code is clear, especially goto an exit point like in your code, there's nothing wrong with it.  Why waste time trying to juggle code around for nothing.  Whereas goto in fortran or basic, that's another story.

rowbearto

  • Senior Community Member
  • Posts: 2335
  • Hero Points: 132
Re: C++ issue with push-tag and friend classes
« Reply #6 on: June 07, 2019, 02:29:55 PM »
I find goto to also be cleaner when trying to break out of an outer loop in C and C++:

Code: [Select]
for (loop1...) {
  for (loop2...) {
    if (some condition)
     goto breakOuter
  }
}
breakOuter:

Sure it could be done without goto but I think it would be HARDER to read and understand - not as clean. It is also more efficient then setting some flag in the inner loop and then checking this flag in each iteration of the outer loop to know whether to exit early.

Where I think goto should not be used is instead of standard loop structures such as for/while/do.while(), or break/continue. But when desired to do things that the language does not offer such as breaking out of nested loops goto can often be cleaner and more efficient.

I've also seen Linus Torvalds posts talking about this being a very valid use of goto.

Also relevant: https://smartbear.com/blog/develop/goto-still-has-a-place-in-modern-programming-no-re/
« Last Edit: June 07, 2019, 02:44:45 PM by rowbearto »

Graeme

  • Senior Community Member
  • Posts: 2796
  • Hero Points: 347
Re: C++ issue with push-tag and friend classes
« Reply #7 on: June 09, 2019, 07:20:52 AM »
Well I have to admit I don't use goto very often but I don't avoid it just because it has a bad reputation.  I used it quite a bit in the function below as it was the natural way to write the code.  I'm challenged for time on this project but even if I wasn't, I wouldn't dream of refactoring it.

Code: [Select]
void maintain_wait_for_list()
{
   wait_for_list_t::iterator     iter;
   wait_for_t &                  wait_data;
   uint                          max_restarts = 0;

   restart_loop :

   if (++max_restarts > 8)
      return;

   for (iter = wait_for_list.begin(); iter != wait_for_list.end(); ++iter)
   {
      wait_for_t &   wait_data = *iter;
      if (wait_data.wait_type == wait_for_t::wait_for_signal_start)
      {
         if (signal_has_started(wait_data.command_id))
         {
            end_wait_for :
            uint32   address = wait_data.logic_restart_address;
            wait_for_list.erase(iter);
            execute_script_block((const char *)get_database_object_address(address), I_NORMAL);
            goto restart_loop;
         }
         else if (wait_data.milliseconds_to_wait > 0)
         {
            if (wait_data.timer.has_time_elapsed_milliseconds(wait_data.milliseconds_to_wait))
               goto end_wait_for;
         }
      }
      else if (wait_data.wait_type == wait_for_t::wait_for_signal_end)
      {
         if (signal_has_finished(wait_data.command_id))
         {
            goto end_wait_for;
         }
         else if (wait_data.milliseconds_to_wait > 0)
         {
            if (wait_data.timer.has_time_elapsed_milliseconds(wait_data.milliseconds_to_wait))
               goto end_wait_for;
         }
      }
      else if (iter->wait_type == wait_for_t::wait_for_time)
      {
         if (wait_data.timer.has_time_elapsed_milliseconds(wait_data.milliseconds_to_wait))
            goto end_wait_for;
      }
      else if (iter->wait_type == wait_for_t::wait_for_nothing)
      {
         goto end_wait_for;
      }
      else
      {
         // FATAL ??
         wait_for_list.erase(iter);
         goto restart_loop;
      }
   }
}

Dennis

  • Senior Community Member
  • Posts: 3961
  • Hero Points: 517
Re: C++ issue with push-tag and friend classes
« Reply #8 on: June 12, 2019, 03:35:48 PM »
I'm glad my punning gave you guys something new to discuss.   ;)