将函数包装器转换为 std::function

Converting a function wrapper to std::function

本文关键字:std function 转换 函数 包装      更新时间:2023-10-16

我的问题是我有一个函数包装器,里面包含一个std::function。我想要完成的是能够将其分配给 std::function - 就像这样:

std::function a = mywrapper; 

它可以工作,但它在此过程中丢失了有关空的信息 - 即使我的包装类中的 std::function 为空,新创建的函数 a 也不会保留此信息 - 它不能转换为布尔值。

如果我的包装器包含一个 nullptr(空(std::function,函数 a 在赋值后会说它是非空的;即它会布尔转换为 true。

有没有办法纠正这种行为?

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

这将解析为 true。它应该解析为假。

下面是 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();
};

我认为这是不可能的,除非语言随着赋值的工作方式而改变。

当你写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;会做你想做的事。