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

问题描述 投票:0回答:2

我想获取存储在容器中的每个函数的返回类型。我试过 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
    }

}
c++ function lambda return-type variant
2个回答
2
投票

fn
的类型是
std::function<Base()>
,因此调用
fn()
的结果总是一个
Base
。那些
std::function
s 包装的 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
    }

}

0
投票

我已经设法解决了这两种不同的方式。

第一种方式:

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.