C ++自动扣除返回类型

时间:2015-04-16 00:51:43

标签: c++ templates c++11

我想编写一个函数,根据不同的输入返回不同的类型,如下所示。

enum MyType
{
    A,
    B
};

template<MyType T> struct MyStruct
{

};

static auto createMyStruct(MyType t)
{
    if(t==A)
        return MyStruct<A>();
    else
        return MyStruct<B>();
}

它没有成功,因为一个汽车有两种返回类型。有没有其他方法可以做到这一点?

3 个答案:

答案 0 :(得分:1)

绝对没有办法让(单个)函数根据运行时决策返回不同的类型。返回类型必须在编译时知道。但是,您可以使用模板函数,这样(感谢@dyp使我简化代码):

#include <iostream>
#include <typeinfo>

enum MyType
{
    A,
    B
};

template<MyType>
struct MyStruct {};

template<MyType type>
MyStruct<type> createMyStruct()
{
    return {};
}

int main()
{
    auto structA = createMyStruct<A>();
    auto structB = createMyStruct<B>();

    std::cout << typeid(structA).name() << std::endl;
    std::cout << typeid(structB).name() << std::endl;
}

答案 1 :(得分:0)

我认为你应该学习abstract factory design pattern

对于MyStruct<A>MyStruct<B>类型的使用对象,您需要通用接口。抽象基类中提供的通用接口。

struct MyStruct
{
    virtual ~MyStruct() {}
    virtual void StructMethod() = 0;
};

struct MyStructA: public MyStrcut
{
    void StructMethod() override {}
};

struct MyStructB: public MyStrcut
{
    void StructMethod() override {}
};

std::unique_ptr<MyStruct> createMyStruct(MyType t)
{
    if(t==A)
        return std::make_unique<MyStructA>();
    else
        return std::make_unique<MyStructB>();
}

答案 2 :(得分:0)

我假设你想写这样的代码:

void foo (MyType t) {
    auto x = createMyStruct(t);
    //... do something with x
}

您正试图在运行时为x派生正确的类型。但是,必须在编译时知道函数的返回类型,并且auto的类型解析也在编译时确定。

您可以改为将代码重构为:

template<MyType T> struct MyStruct
{
    //...
    static void foo () {
        MyStruct x;
        //... do something with x
    }
};

这个想法是编写一个foo()函数,它唯一的区别就是它操作的东西的类型。此函数封装在类型本身中。如果您在MyTypeMyStruct<MyType>::foo之间存在映射,则现在可以做出运行时决策。

typedef std::map<MyType, void(*)()> MyMap;

template <MyType...> struct PopulateMyMap;

template <MyType T> struct PopulateMyMap<T> {
    void operator () (MyMap &m) {
        m[T] = MyStruct<T>::foo;
    }
};

template <MyType T, MyType... Rest> struct PopulateMyMap<T, Rest...> {
    void operator () (MyMap &m) {
        m[T] = MyStruct<T>::foo;
        PopulateMyMap<Rest...>()(m);
    }
};

template<MyType... Types> void populateMyMap (MyMap &m) {
    PopulateMyMap<Types...>()(m);
}

//...
    populateMyMap<A, B>(myMapInstance);

然后,做出运行时决定:

void foo (MyType t) {
    myMapInstance.at(t)();
}