std :: bind()中的static_cast的Functor版本

时间:2012-01-10 16:10:29

标签: c++ bind functor static-cast

我尝试实现static_cast的仿函数版本,以便在std::bind()中使用。

我知道Boost ll_static_cast<K>()(请参阅using static_cast with boost::bind),但我现在没有使用Boost。

Why do several of the standard operators not have standard functors?中有一个代码示例,但它不会在GCC 4.2.1上编译:

template <typename Target>
struct StaticCast
{
    template <typename Source>
    Target operator()(Source&& source) const
    {
        return static_cast<Target>(source);
    }
}

我设法得到了一些东西可以编译,但我不确定它是否正确:

template <class Target>
struct StaticCast : public std::unary_function<void, Target> {
    template <class Source>
    Target operator()(Source& src) const {
        return static_cast<Target>(src);
    }
};

有人可以告诉我这个版本是否正确,如果是这种情况,为什么我需要std::unary_function,这在前面的代码示例中没有使用?

用法:

std::vector<BaseObject*> vec;  // BaseObject* are known to be of type 
    // DerivedObject* of course, please don't ask me how or why...

std::for_each(vec.begin(), vec.end(),
    std::bind(&DerivedObject::doStuff,
        std::bind(StaticCast<DerivedObject*>(), std::placeholders::_1),
    "with some string"));

3 个答案:

答案 0 :(得分:0)

第一个不起作用的一个原因可能是因为您在不支持C ++ 11的编译器上使用rvalue引用。

您需要std::unary_function的原因是为std::result_of用于推断结果类型的类启用std::bind,因为C ++ 98中没有decltype。

如果您查看std::unary_function,您会看到它会根据您传递的模板参数定义类型result_type,该参数由std::result_ofstd::bind直接使用

答案 1 :(得分:0)

嗯,通常你的代码很糟糕:

首先,在请求非const引用时,您可能会遇到临时对象和r值的问题

例如

float f = StaticCast<float>()(4);

甚至不会编译。

然后,你在投射时复制对象。可能不是你想要的。

源代码免费move语义引起的缺点

答案 2 :(得分:0)

鉴于在C ++ 03中缺乏完美的转发,你必须通过重载来实现:

template<class Target>
struct StaticCast
{
    typedef Target result_type;

    template<class Source>
    Target operator ()(Source& src) const
    {
        return static_cast<Target>(src);
    }

    template<class Source>
    Target operator ()(Source const& src) const
    {
        return static_cast<Target>(src);
    }
};

请注意,我明确为typedef制作result_type而非继承std::unary_function<>。原因是std::unary_function<>的第一个模板参数应该是operator()的参数类型,但由于我们的operator()是模板,我们无法提前知道,所以它是不诚实地提供一个(尤其是void,这意味着operator()是无效的,而事实上它是一元的。)


另外,为了完整起见,这是函数的正确C ++ 11版本:

template<class Target>
struct StaticCast
{
    template<class Source>
    Target operator ()(Source&& source) const
    {
        return static_cast<Target>(std::forward<Source>(source));
    }
}