1

我尝试实现一个仿函数版本,static_cast用于std::bind().

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

为什么有几个标准运算符没有标准函子中有一个代码示例?但它不会在 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"));
4

3 回答 3

1

鉴于 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);
    }
};

请注意,我明确地制作了typedefforresult_type而不是继承自std::unary_function<>. 原因是第一个模板参数 tostd::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));
    }
}
于 2012-01-10T17:03:37.517 回答
0

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

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

如果您看一下,std::unary_function您会发现它result_type从您传递的模板参数中定义了类型,而后者又被std::result_ofstd::bind直接使用。

于 2012-01-10T16:28:33.597 回答
0

好吧,通常您的代码很糟糕:

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

例如

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

甚至不会编译。

然后,您在投射时制作对象的副本。它可能不是你想要的。

没有move语义上的缺点的源示例

于 2012-01-10T16:41:30.590 回答