0

I have a program making use of boost::signals2. I need to return a non-copyable value. In order to achieve this, I tried to change the combiner template parameter. The curious thing about this is that inside the combiner I get an error.

This works:

struct Combiner {
    using result_type = NonCopyable;

   template <class Iter>
   NonCopyable operator()(Iter b, Iter e) {
         return NonCopyable(something);
   }
};

using SignalType = boost::signals2::signal<NonCopyable (), Combiner>;

But at the moment I try to dereference an iterator inside Combiner::operator(), things get messed up.

struct Combiner {
    using result_type = NonCopyable;

   template <class Iter>
   NonCopyable operator()(Iter b, Iter e) {
         return *b;
   }
};

std::is_const<Iter> returns false. std::is_reference<decltype(*b)> is returning true.

I cannot figure out why I have the error, but I see the wrong overload is selected here:

void assign_value(argument_type val) { get_impl() = val; }
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
void assign_value(rval_reference_type val) { get_impl() = static_cast<rval_reference_type>(val); }
#endif

Rvalue references are activated, I checked it in an example program and I am using c++14 flag in gcc. Any idea?

EDIT: Full example.

#include <memory>
#include <boost/signals2.hpp>


class NonCopyable {
    std::unique_ptr<int> _i;
public:
    explicit NonCopyable(int i) : _i(new int(i)) {}
}; 

struct Combiner {
        using result_type = NonCopyable;

       template <class Iter>
       NonCopyable operator(Iter b, Iter b) const {
             return std::move(*b);
       }
    };

using SignalType = boost::signals2::signal<NonCopyable(), Combiner>;

int main() {
   SignalType s;
   s.connect([] { return NonCopyable(3); });
   s();
}
Germán Diago
  • 7,473
  • 1
  • 36
  • 59
  • 2
    `is_reference` does not imply `is_rvalue_reference`. For this to work, `operator()` would need to return a `NonCopyable&`, no? – Richard Hodges Aug 02 '17 at 10:41
  • I tried to move the result also. It won't work. I did `return std::move(*b)`. But the return is not what happens in my actual code actually. Even doing this inside the operator()() triggers the error about a copy: `*b;` – Germán Diago Aug 02 '17 at 10:48
  • @RichardHodges the issue seems to be inside optional. The wrong overload in optional is chosen and it is calling `assign_value` even when a simple dereference is done without assigning anything. A bit confused about this. – Germán Diago Aug 02 '17 at 11:00
  • Are you able to reproduce in a full (tiny) example so we can play with it? – Richard Hodges Aug 02 '17 at 16:30
  • Yes, we need a SSCCE. – sehe Aug 02 '17 at 18:56

0 Answers0