Преобразование оболочки функции в std :: function - PullRequest
0 голосов
/ 19 октября 2018

Моя проблема в том, что у меня есть оболочка функции, которая содержит std :: function внутри.Что я хочу сделать, так это уметь назначать его в std :: function - вот так:

std::function a = mywrapper; 

Работает, но в процессе теряет информацию о пустоте - даже если std :: functionвнутри моего класса-обертки пусто, вновь созданная функция a не будет сохранять эту информацию - ее нельзя привести к bool.

Если моя оболочка содержит nullptr (пустой) std :: function, функция a после присваивания скажет, что она не пуста;то есть оно будет приведено к истине.

Есть ли способ исправить это поведение?

FunctionWrapper<void()> wrapper;
std::function<void()> std;
std = wrapper;
std::cout << std::boolalpha << bool(std) << std::endl;

Это приведет к истине.И это должно разрешиться в false.

Вот заголовок класса FunctionWrapper:

template < class >
class FunctionWrapper;

template<class R, class... ArgTypes>
class FunctionWrapper<R(ArgTypes...)>
{
private:
    std::function<R(ArgTypes...)> func = nullptr;

public:
    FunctionWrapper() = default;
    FunctionWrapper(const FunctionWrapper&) = default;
    FunctionWrapper(FunctionWrapper&&) = default;
    FunctionWrapper(const boost::function<R(ArgTypes...)>&);
    FunctionWrapper(boost::function<R(ArgTypes...)>&&);
    template<class F> FunctionWrapper(F);

    FunctionWrapper& operator=(const FunctionWrapper&) = default;
    FunctionWrapper& operator=(FunctionWrapper&&) = default;
    FunctionWrapper& operator=(boost::function<R(ArgTypes...)>&);
    FunctionWrapper& operator=(boost::function<R(ArgTypes...)>&&);
    template<class F> FunctionWrapper& operator=(F&&);

    ~FunctionWrapper() = default;

    //R operator()(ArgTypes...);

    operator std::function<R(ArgTypes...)>();
    operator boost::function<R(ArgTypes...)>();
    explicit operator bool();

};

1 Ответ

0 голосов
/ 19 октября 2018

Я не думаю, что это возможно, если не считать смены языка в зависимости от того, как работает назначение.

Когда вы пишете std = wrapper, это синтаксический сахар для std.operator=(wrapper).Мы действительно вызываем эту функцию.Это не похоже на инициализацию, где мы также рассматриваем функции преобразования на более высоком уровне .В общем, у нас есть function::operator= опций:

function& operator=( const function& other );                             // #1
function& operator=( function&& other );                                  // #2
function& operator=( std::nullptr_t );                                    // #3
template< class F >  function& operator=( F&& f );                        // #4
template< class F >  function& operator=( std::reference_wrapper<F> f );  // #5

#3 и #5 нежизнеспособны, #4 означает, что у вас есть соответствующий operator() и #1 и #2 - оба по одной и той же причине, а также из-за наличия вашей функции преобразования.Но #4 является точным совпадением, тогда как ни #1, ни #2 не являются, поэтому он выигрывает.Полная остановка.

Единственный способ сделать #2 предпочтительным #4 (что вы действительно хотите) - это сделать #4 не кандидатом.Но единственный способ сделать #4 не кандидатом - это сделать wrapper не вызываемым.Что делает его ... вовсе не оберткой.

Так что вам здесь в основном не повезло.

Обратите внимание, что std::function<void()> std = wrapper; делает то, что вы хотите.

...