简体   繁体   中英

boost c++ method returning different object types

I want to port some of my Python code to C++ code. The problem which I encounter now is when a function may return different object types - say a variable of one class or another depending on some condition (but not on the type of an argument), almost like so:

def somefunc(var):
  # obj1 is instance of Class1
  # obj2 is instance of Class2
  #.... some other code
  if var == 1:
      return obj1
  elif var == 2:
      return obj2

And lets say I have corresponding classes implemented in C++. And now what I want is to somehow return from a method either an instance of one class or of another. I do not know how to approach this task - how my C++ method should look like and how BOOST_PYTHON_MODULE should look like. If somebody could provide the simplest in the world examle with a C++ function returning instanced of different classes, that would be greatly appreciated.

As said in the comments, the real question here is: How to return different types from the same function in C++?

We can use boost.variant for that. Here is a small example that demonstrates the basic feature we need:

#include <iostream>
#include <string>
#include <boost/variant.hpp>

boost::variant<int, std::string> fun (bool i) {
    if (i)
        return "Hello boost!\n";
    return 4711;
}

int main()
{
    std::cout << fun(true) << fun(false) << std::endl;
}

The output will be

Hello boost!
4711

A more detailed introduction to the features of boost.variant can be found in their tutorial .

If the possible return types are not known at compile time or their number is big, we can also use boost.any . This is more flexible, but a little bit less straight forward:

#include <iostream>
#include <string>
#include <boost/any.hpp>

using namespace std::literals::string_literals;

boost::any fun (bool i) {
    if (i)
        return "Hello boost!\n"s;
    return 4711;
}

int main()
{
    std::cout << boost::any_cast<std::string>(fun(true)) 
              << boost::any_cast<int>(fun(false)) << std::endl;
}

If possible, boost.variant is most likely the better tool for your problem.

If that classes could inherit from one interface you could go with abstract interface class.

//Interface, abstract class .h file

#pragma once

namespace test
{
    class IClass0
    {
        public:
            virtual bool DoStuff() =0;      
    };
}


//Class1 .h file
#pragma once
#include "IClass0.h"

    namespace test
    {
        class Class1 : public IClass0
        {
            public:
                virtual bool DoStuff();     
        };
    }


//Class2 .h file
#pragma once
#include "IClass0.h"

    namespace test
    {
        class Class2 : public IClass0
       {
            public:
               virtual bool DoStuff();      
        };
    }

And than you could return pointer to created instance as Interface

 unique_ptr<IClass0> ReturnClassInstance()
 {
     if(condition1)
     {
        unique_ptr<Class1> ptr (new Class1());
        return move(ptr);
     }
     else
     {
        unique_ptr<Class2> ptr (new Class2());
        return move(ptr);
     }
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM