我尝试实现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"));
答案 0 :(得分:0)
第一个不起作用的一个原因可能是因为您在不支持C ++ 11的编译器上使用rvalue引用。
您需要std::unary_function
的原因是为std::result_of
用于推断结果类型的类启用std::bind
,因为C ++ 98中没有decltype。
如果您查看std::unary_function
,您会看到它会根据您传递的模板参数定义类型result_type
,该参数由std::result_of
或std::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));
}
}