Opened 5 years ago

Last modified 5 years ago

#8463 new Bugs

function_output_iterator: MSVC warning C4512

Reported by: Mike Cowperthwaite <michael.cowperthwaite@…> Owned by: jeffrey.hellrung
Milestone: To Be Determined Component: iterator
Version: Boost 1.52.0 Severity: Problem
Keywords: Cc:

Description

In boost/function_output_iterator the struct function_output_iterator::output_proxy yields this warning: "assignment operator could not be generated." I see this primarily using signals2, where the iterator class is created using boost::signals2::detail::does_nothing as the iterator template argument.

The warning is due to the proxy's const data member, and probably not dependent on the iterator template argument.

The struct also has a templated operator= defined, but not of the sort that would work as a copy-assignment.

Other libraries (fusion, spirit, statechart in particular) have implemented do-nothing assignment operators (or just declarations) to overcome similar symptoms. If I do the same for this class in my local copy -- simply add a declaration for this particular signature:

  private:
    output_proxy& operator=(output_proxy const &src);

the warning goes away; however, I can't be sure this doesn't break something. It seems unlikely, as I can run code with the warning and my signals seem to work just fine.

Change History (5)

comment:1 Changed 5 years ago by viboes

Component: Noneiterator
Owner: set to jeffrey.hellrung

comment:2 Changed 5 years ago by Paul Saville <boost_8463@…>

MSVC emits warning C4512 because output_proxy contains a reference member variable, which makes default member-wise assignment impossible. I don't yet understand why the compiler refuses to use the operator= template member function to generate an acceptable (although apparently flawed) assignment operator. Changing the UnaryFunction? reference to an ordinary member variable made the warning go away for me. This changes the behaviour so it's not a fix, just an experiment. I also added an assert() to determine whether the operator= template is ever actually called at runtime.

  struct output_proxy
  {
    output_proxy( UnaryFunction& f ) : m_f( f ) {}
    template< class T > output_proxy& operator=( const T& value )
    {
      m_f( value );
      assert( false );
      return *this;
    }
//    UnaryFunction& m_f;
    UnaryFunction m_f;
  };

I'm also somewhat concerned about function_output_iterator::operator*(). It returns an output_proxy instance containing a reference to private member function_output_iterator::m_f, which is a strange thing to do. If there is an esoteric idiom in play here, can anyone point out what it is?

comment:3 Changed 5 years ago by guy@…

This appears to be a duplicate of #3857. However, that ticket has been closed with the advice to silence the warning or submit a patch. Does the problem solution above constitute a patch?

comment:4 Changed 5 years ago by Mike Cowperthwaite <michael.cowperthwaite@…>

1) fmhess's 'advice' at that other bug looks like knee-jerk Microsoft-blaming, altho he might technically be right that these warnings are spurious. (a) As noted in the original report here, several Boost libraries have already taken steps to prevent them. (b) A spurious warning here might be a non-spurious warning elsewhere; and this warning cannot be suppressed using MS's #pragma warning.

2) Not sure which "problem solution above" you're referring to: there is code in comment 2, and code in the original report. The code in the original report is similar to the solutions I found in other Boost libraries. The code in comment 2 looks like it might work fine; whether copying a UnaryFunction object with every instance of output_proxy would be undesirable overhead, I cannot say.

I'm curious to know if Paul Saville's assert() has ever been triggered. (Also, Paul correctly pinned the cause on the "reference member variable," not a "const data member" as I originally stated.)

comment:5 in reply to:  4 Changed 5 years ago by Guy Bolton King <guy@…>

Replying to Mike Cowperthwaite <michael.cowperthwaite@…>:

2) Not sure which "problem solution above" you're referring to: there is code in comment 2, and code in the original report.

Sorry, the code in the original report.

I'm curious to know if Paul Saville's assert() has ever been triggered. (Also, Paul correctly pinned the cause on the "reference member variable," not a "const data member" as I originally stated.)

I would imagine it is never triggered: if you only get a C4512 warning, but no errors about the assignment operator not existing, then surely it's not being called by anything.

Is there anyone from Boost looking at this who can say whether the proposed code in the original report is acceptable as a patch, or whether more is required to fix this? Incidentally fmhess appears to one of the authors of signals2 (according to the docs anyway), so I'm hoping he's changed his mind about this since the response to #3857.

Note: See TracTickets for help on using tickets.