如何正确转发/换行static_cast?

How to correctly forward/wrap static_cast?

本文关键字:cast static 换行 何正确 转发      更新时间:2023-10-16

基本上,我需要一个static_cast函数包装器用作谓词(用于转换(,因为static_cast直接不能以这种方式使用。这次不首选 Lambda。我的实现:

template<typename T> 
struct static_cast_forward{
template<class U>
T operator()(U&& u) const {
return static_cast<T>(std::forward<U>(u));
}
};

首先,虽然我对右值引用等有基本的了解。我想验证这是否是实现此转发/包装器的正确方法?

其次,询问是否有任何stdboost库已经提供了此功能?

额外:你会以同样的方式转发其他演员吗?

实际案例:

我的实际情况是与boost::range一起使用,例如:

//auto targetsRange = mixedRange | boost::adaptors::filtered(TYPECHECK_PRED) | boost::adaptors::transformed(static_cast_forward<TARGET_PTR_TYPE>());

工作实例:

#include <algorithm>
template<typename T>
struct static_cast_forward {
template<class U>
T operator()(U&& u) const {
return static_cast<T>(std::forward<U>(u));
}
};
//example 1:
void test1() {
std::vector<double> doubleVec{1.1, 1.2};
std::vector<int> intVec;
std::copy(doubleVec.begin(), doubleVec.end(), intVec.end());//not ok (compiles, but gives warning) 
std::transform(doubleVec.begin(), doubleVec.end(), std::back_inserter(intVec), static_cast_forward<int>()); //ok
}
//example 2:
struct A {
virtual ~A() {} 
};
struct B : public A {
};
struct C : public A {
};
void test2() {
std::vector<A*> vecOfA{ new B, new B};
std::vector<B*> vecOfB;
//std::transform(vecOfA.begin(), vecOfA.end(), std::back_inserter(vecOfB), static_cast<B*>); //not ok: syntax error..
std::transform(vecOfA.begin(), vecOfA.end(), std::back_inserter(vecOfB), static_cast_forward<B*>() ); //ok
}

澄清问题后的添加。

在这两种情况下,您都不需要std::forward任何东西,因为没有什么可移动的,您只需要一个石膏。但是,如果您也想推广到可移动类型,那么您的实现对我来说似乎很好。只是不要称它为forward,因为它不是forward.据我所知,std没有什么可以模仿你的struct.

所以我只想添加test3()真正需要移动的内容:

struct B { };
struct D { 
explicit D(B&&) { }   // Note: explicit!
};
void test3()
{
std::vector<B> vb{B{}, B{}};
std::vector<D> vd;
// Won't compile because constructor is explicit
//std::copy(std::make_move_iterator(vb.begin()), std::make_move_iterator(vb.end()), std::back_inserter(vd));
// Works fine
std::transform(std::make_move_iterator(vb.begin()), std::make_move_iterator(vb.end()), std::back_inserter(vd), static_cast_forward<D>());
}

在澄清问题之前回答。

如果我正确理解了您的意图,那么这就是您想要的:

template<typename T>
struct static_cast_forward {
template<class U>
decltype(auto) operator()(U&& u) const
{
if constexpr (std::is_lvalue_reference_v<U>)
return static_cast<T&>(u);
else
return static_cast<T&&>(u);
}
};

然后你有:

struct B { };
struct D : B { };
void foo() {
D d;
static_cast_forward<B> scf_as_B;
static_assert(std::is_same_v<decltype(scf_as_B(D{})), B&&>);
static_assert(std::is_same_v<decltype(scf_as_B(d)), B&>);
}