AlessandroF
AlessandroF

Reputation: 572

How to let a C++ function return different types?

Look at this code:

#include<iostream>

enum class DataStructure{stack,queue};

template <typename T>
T foo(DataStructure ds){
  if(ds == DataStructure::stack){
    return 1;
  }
  else if(ds == DataStructure::queue){
    return 3.14F;
  }
}

int main(){
  std::cout<<foo(DataStructure::stack);
}

Obviously it does not compile, giving error: no matching function for call to ‘foo(DataStructure)’
But you understand what I want to do, is there a way to do that? Basically foo must return a different object or fundamental type depending on the value of the enum.
I apologize for the basic question.

Upvotes: 1

Views: 347

Answers (5)

You need to declare foo's variable type because you are using a template this may solve your problem because your function return's double:

 std::cout << foo<double> (DataStructure::stack);

Upvotes: 0

Pete Becker
Pete Becker

Reputation: 76523

Tagged dispatch:

struct queue {};
struct stack {};

int foo(stack) { return 1; }
float foo(queue) { return 3.14f; }

int main() {
    std::cout << foo(stack{}) << '\n';
    std::cout << foo(queue{}) << '\n';
    return 0;
}

Upvotes: 0

Lasersk&#246;ld
Lasersk&#246;ld

Reputation: 2235

Try std::variant. It can return different values in runtime. It could look something like this.

#include <iostream>
#include <variant>

enum class DataStructure{stack,queue};

std::variant<int, double> foo(DataStructure ds){
  if(ds == DataStructure::stack){
    return 1;
  }
  else if(ds == DataStructure::queue){
    return 3.14F;
  }
}

// Updated version
int main(){
  std::visit(
      [](auto value) {
          std::cout << value;
      }, foo(DataStructure::stack));
}

// Version without visit
int main(){
  auto value = foo(DataStructure::stack);
  if (std::holds_alternative<double>(value)) 
  {
    std::cout << get<double>(value);
  }
  else {
    std::cout << get<int>(value);
  }
}

Upvotes: 2

super
super

Reputation: 12978

If the passed in enum is a compile-time constant you can pass it as a template parameter and make the function return different types accordingly.

#include<iostream>

enum class DataStructure{stack,queue};

template <DataStructure T>
auto foo(){
  if constexpr (T == DataStructure::stack){
    return 1;
  }
  else if constexpr (T == DataStructure::queue){
    return 3.14F;
  }
}

int main(){
  std::cout<<foo<DataStructure::stack>();
}

Requires c++17 for the if constexpr, but you can achieve the same thing with a template specialization in earlier versions.

Upvotes: 7

Tom Moers
Tom Moers

Reputation: 1261

Have a look at std::variant which allows you to attach type-safe data to your various cases.

Upvotes: 0

Related Questions