c++ 如何推导存储在容器中的每个函数(在派生类上)的返回类型

vsdwdz23  于 2023-04-01  发布在  其他
关注(0)|答案(2)|浏览(78)

我想获取存储在容器中的每个函数的返回类型。我已经尝试了std::any和std::variant,但我无法解决这个问题。详细信息如下:

#include <random>
#include <vector>
#include <functional>
using namespace std;

class Base
{
public: virtual void test() { }
};

class Derived1 : public Base
{
public: virtual void test() { }
};

class Derived2 : public Base
{
public: virtual void test() { }
};

int main ()
{
    std::vector<std::function < Base(void)>> b;

    b.push_back([&]() { return Derived1(); });
    b.push_back([&]() { return Derived2(); });
    b.push_back([&]() { return Base(); });

    std::shuffle(b.begin(), b.end(), std::default_random_engine {});

    for (auto fn : b)
    {
        // Here I would like to reach the derived classes from "fn" somehow and use it like "new Derived1"
        //decltype(fn)::result_type ----------> this gives me Base only but i want the derived as well
    }

}
mzsu5hc0

mzsu5hc01#

fn的类型是std::function<Base()>,因此调用fn()的结果总是Basestd::function Package 的lambdas表达式返回其他类型并不重要。这些返回值用于初始化Base类型的对象。
记住,在C++中,多态性只适用于引用和指针。虽然Base&Base*可以引用Derived1对象,但Base对象不引用任何东西。它是一个Base对象,永远不会是其他任何东西。
如果你想要多态性,你需要你的函数返回指针:

int main ()
{
    std::vector<std::function<std::unique_ptr<Base>()>>> b;

    b.push_back([&]() { return std::make_unique<Derived1>(); });
    b.push_back([&]() { return std::make_unique<Derived2>(); });
    b.push_back([&]() { return std::make_unique<Base>(); });

    std::shuffle(b.begin(), b.end(), std::default_random_engine {});

    for (auto fn : b)
    {
        fn()->test();  // Will call the correct overridden test
                       // depending on the runtime type of the
                       // object pointed to by the returned unique_ptr
    }

}
au9on6nz

au9on6nz2#

我设法用两种不同的方法解决了这个问题。
第一种方法:

int main()
{
    std::vector<std::function<Base& ()>> b;

    b.push_back([]() -> Base& { static Derived1 d1; return d1; });
    b.push_back([]() -> Base& { static Derived2 d2; return d2; });
    b.push_back([]() -> Base& { static Base b; return b; });

    std::shuffle(b.begin(), b.end(), std::default_random_engine{});

    for (auto& fn : b)
    {
        if (auto derived2_ptr = dynamic_cast<Derived1*>(&fn()))
        {
            derived2_ptr->test();
            Derived1* var = new Derived1(*derived2_ptr);
            var->test();
        }
        else if (auto derived2_ptr = dynamic_cast<Derived2*>(&fn()))
        {
            derived2_ptr->test();
            Derived2* var = new Derived2(*derived2_ptr);
            var->test();
        }
    }

    return 0;
}

第二种方法:

int main()
{
    std::vector<std::function<std::shared_ptr<Base>()>> b;

    b.push_back([&]() { return std::make_shared<Derived1>(); });
    b.push_back([&]() { return std::make_shared<Derived2>(); });
    b.push_back([&]() { return std::make_shared<Base>(); });

    std::shuffle(b.begin(), b.end(), std::default_random_engine{});

    for (auto fn : b)
    {
        if (auto derived1_ptr = std::dynamic_pointer_cast<Derived1>(fn()))
        {
            derived1_ptr->test();
            shared_ptr<Derived1> var = std::make_shared<Derived1>(*derived1_ptr);
            var->test();
        }
        else if (auto derived2_ptr = std::dynamic_pointer_cast<Derived2>(fn()))
        {
            derived2_ptr->test();
            shared_ptr<Derived2> var = std::make_shared<Derived2>(*derived2_ptr);
            var->test();
        }
    }

    return 0;
}

相关问题