std::bind() 中 static_cast 的仿函数版本

发布于 2024-12-25 20:33:42 字数 1346 浏览 7 评论 0原文

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

我知道 Boost ll_static_cast() (请参阅将 static_cast 与 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"));

I try to implement a functor version of static_cast for use in std::bind().

I am aware of Boost ll_static_cast<K>() (see using static_cast with boost::bind), but I am not using Boost right now.

There is a code example in Why do several of the standard operators not have standard functors? but it won't compile on GCC 4.2.1:

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

I managed to get something to compile, but I am not sure it's correct:

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

Can someone tell me if this version is correct, and if this is the case, why I need std::unary_function which is not used in the previous code example?

Usage:

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"));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

摇划花蜜的午后 2025-01-01 20:33:42

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

请注意,我明确为 result_type 创建了 typedef,而不是继承来自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));
    }
}

Given the lack of perfect forwarding in C++03, you'll have to make due with overloads:

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

Note that I'm explicitly making a typedef for result_type rather than inheriting from std::unary_function<>. The reason is that the first template parameter to std::unary_function<> is supposed to be operator()'s argument type, but because our operator() is a template we can't know this in advance, so it's disingenuous to supply one in the first place (especially void, which would imply that operator() is nullary, when in fact it is unary).


Also, for completeness' sake, here is the correct C++11 version of the functor:

template<class Target>
struct StaticCast
{
    template<class Source>
    Target operator ()(Source&& source) const
    {
        return static_cast<Target>(std::forward<Source>(source));
    }
}
深空失忆 2025-01-01 20:33:42

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

您需要 std::unary_function 的原因是为您的类启用 std::result_ofstd::bind 使用该类来推导结果类型,因为 C++98 中没有 decltype。

如果您查看 std::unary_function ,您会发现它从您传递的模板参数中定义了类型 result_type ,该类型又由 std:: 使用直接 result_of 或 std::bind

One reason the first one doesn't work is probably because you are using rvalue references on a compiler that doesn't support C++11.

The reason you need std::unary_function is to enable std::result_of for your class which std::bind uses to deduce the result type, since there is no decltype in C++98.

If you look at std::unary_function you will see that it defines the type result_type from the template arguments you pass, which is in turned used by std::result_of or std::bind directly.

半葬歌 2025-01-01 20:33:42

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

首先,你可能会遇到临时对象和右值的问题,同时请求它们的非常量引用,

例如

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

甚至无法编译。

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

源示例没有由于move语义而产生的缺点

Well, generally your code is bad:

First, you may have troubles with temporary objects and r-values while requesting non-const reference for them

for example

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

won't even compile.

Then, you make a copy of object while casting. It may be do not that you want.

Source example free of that disadvantages due to move semantics

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文