c++ - 如何 dynamic_cast 参数中带有不匹配引用修饰符的可变参数模板?

标签 c++ c++11 variadic-templates dynamic-cast perfect-forwarding

我有一个类层次结构,其中基类包含一个函数,该函数根据接收到的参数测试 dynamic_castthis 指针转换为派生模板类型。

问题是 dynamic_cast 运算符会检查参数是否完全匹配,同时考虑它们是否为 ref。我需要以下示例来处理这两种情况,有没有办法做到这一点?

template <typename... P>
struct Derived;

struct Base
{
    virtual ~Base() {}

    template <typename... P>
    void doCast(P&&... p) {
        Derived<P...> *res=dynamic_cast<Derived<P...> *>(this);
        if (!res)
            std::cout<<"Failed."<<std::endl;
        else {
            std::cout<<"Success."<<std::endl;
            res->doSomethingWithP(std::forward<P>(p)...);
        }
    }
};

template <typename... P>
struct Derived: public Base
{
    void doSomethingWithP(P... p) {
        /*Whatever, doesn't matter*/
    }
};

int main(int argc, char **argv)
{
    Derived<int, int, int> derived;
    Base *b=&derived;

    int x=10;
    int y=20;
    int z=30;

    //The two calls must succeed.
    b->doCast(x,y,z); //Failed.
    b->doCast(10,20,30); //Success.

    return 0;
}

Derived 可以接受同时是值、引用和指针的类型 - cv - 限定或不限定。

最佳答案

只是将我的评论移至答案。在典型情况下,如果两个 Derived<int>Derived<int const&>允许作为类型,Base::doCast可能必须为每个参数类型执行两个不同的转换,或者 2^N总 Actor 。这是不可行的。

但是,您可以改为 (1) 要求 Derived的模板参数不是引用,并且 (2) 让它通过引用获取其参数。所以我们只删除所有 P 的引用小号:

template <typename... P>
void doCast(P&&... p) {
    if (auto res = dynamic_cast<Derived<std::remove_reference_t<P>...>*>(this)) {
        std::cout << "Success." << std::endl;
        res->doSomethingWithP(p...); // NOT forward
    }
    else {
        std::cout << "Failed." << std::endl;
    }
}

并在另一边引用,这样我们就不会产生额外的拷贝:

template <typename... P>
struct Derived: public Base
{
    void doSomethingWithP(P&... ) {
        /*Whatever, doesn't matter*/
    }
};

然而,这仍然让我们做出Derived<int&> ,这将永远在此模型中工作。因此,让我们明确禁止这样做。首先是一些样板文件:

template<bool...> struct bool_pack;

template<bool f, bool... bs> 
using all_same = std::is_same<bool_pack<bs..., f>, bool_pack<f, bs...>>;

template <bool... bs>
using none = all_same<false, bs...>;

然后:

template <typename... P>
struct Derived: public Base
{
    static_assert(none<std::is_reference<P>::value...>::value, 
                  "Can't make Derived with references");
    ...
};

关于c++ - 如何 dynamic_cast 参数中带有不匹配引用修饰符的可变参数模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31434403/

相关文章:

c++ - C++ 中 std::map 的持久化

c++ - 用于绘制 C/C++ 结构、指针等的快速草图工具

c++ - 有没有办法在 Mac 上为 OpenCL 启用双 vector ?

c++ - 试图更好地理解 C++ 大括号初始化语法

c++ - VS2015错误C2976

c++ - 初始化一个全局的 const POD 结构;针对特定成员

c++ - 返回迭代器以 boost 适配器转换的容器

c++ - 参数包扩展问题

c++ - 接受一组对象类型的所有组合可能性作为在 C++ 中运行的参数

c++ - 将可变参数模板参数解包到初始化列表中