c++ - 如何正确转发/包装 static_cast?

标签 c++ generic-programming static-cast perfect-forwarding

基本上,我需要一个 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 库已经提供此功能?

额外:你会用同样的方式转发其他 Actor 吗?

实际案例:

我的实际情况是与 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&>);
}

关于c++ - 如何正确转发/包装 static_cast?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52165367/

相关文章:

c++ - Opengl 64 位窗口

c - C 中的泛型编程 - void*- const-correctness

c++ - 使用静态转换,因为动态转换失败。不好的做法?

c++ - 替换 C++ 中的 delete,错误信息

c++ - 对于每个模板类型,一个集合类型的参数

c++ - 需要有关 boost 同步对象的教程

C++ 通用包装器类,它为某些函数添加了额外的处理

c++ - 在不同类型之间转换 const 指针

c++ - 错误 C2440 : 'type cast' : cannot convert from 'overloaded-function' to 'HOOKPROC'

java - 您如何强制将泛型包含在特定类中?