[英]How to correctly forward/wrap static_cast?
基本上,我需要使用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));
}
};
首先,雖然我對rvalue引用等有基本的了解,但是我想驗證這是否是實現此轉發/包裝的正確方法?
其次,請問是否有任何std
或boost
庫已經提供了此功能?
額外:您會以同樣的方式轉發其他演員嗎?
實際情況:
我的實際情況是與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&>);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.