0

I am finding connected components of a graph.
Condition : Those components should not be printed in same function, but they should be printed in calling function ( i.e. int main() )

I have gone through the link but got some error. Returning multiple values from a C++ function

  tuple <vector<int>&, int > connected( vector<int>& store, ...)        

  {
       int component_size = 0;

      // code          

       return make_tuple ( store, component_size);
  }

   int main()
   {
       // code 

       for( int i = 0 ; i < V; i++ )
           {
              if( !visited[i])
                 {
                     tie( ans, compo_size ) =  connected(edges, 
                          visited, myQ, store, V, i);

                     for(int i = 0 ; i < compo_size; i++ )
                         {
                             cout<< ans[i] <<" ";
                         }
                 }
           }
   }

There are few errors :

error: could not convert 'std::make_tuple(_Elements&& ...) [with _Elements = {std::vector >&, int&}](component_size)' from 'std::tuple >, int>' to 'std::tuple >&, int>'
         return make_tuple ( store, component_size);    
                       ^ 
error: invalid initialization of reference of type 'std::vector&' from expression of type 'std::vector'
          tie( ans, compo_size ) =  connected(edges, visited, myQ, store, V, i);
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
user1745866
  • 89
  • 1
  • 11

2 Answers2

1

How to return multiple values (vector and one int value) through function

A function can have at most one return value.

Returning more objects can be emulated by either

  • modifying one or more objects that are global or are referenced by arguments through indirection or by
  • returning an object of class type that has multiple sub objects.

You've attempted the latter approach through the use of tuple class template. The reason it doesn't work is explained in the documentation:

template< class... Types >
tuple<VTypes...> make_tuple( Types&&... args );

For each Ti in Types..., the corresponding type Vi in VTypes... is std::decay<Ti>::type unless application of std::decay results in std::reference_wrapper<X> for some type X, in which case the deduced type is X&.

As such, your invocation of make_tuple is deduced to return tuple <vector<int>, int > which is wrong because the function is supposed to return tuple <vector<int>&, int > instead. This can be fixed using std::ref so that the correct type is deduced:

std::make_tuple(std::ref(store), component_size);
Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326
1

As eerorika mentioned, you could use std::ref() as follow:

std::tuple <std::vector<int>&, int > connected( std::vector<int>& store, ...)
{
   int component_size = 0;

   // code

   return std::make_tuple ( std::ref(store), component_size);
}

However, there is really no point in returning a reference to the input vector since it is already a non-const reference on input. So changing the vector in place is going to be enough. On return you get a modified version. However, that's probably not what you are looking to do (i.e. you probably wanted to make a copy of store and return the copy with the other arrays appended...)

That also means you're going to have yet another copy when you create the tuple:

std::tuple <std::vector<int>, int > connected( std::vector<int>& store, ...)
{
   int component_size = 0;

   std::vector<int> result;

   // or maybe a straight copy, depends on your needs in "code"
   //std::vector<int> result(store);

   // code

   return std::make_tuple ( result, component_size);
}

As mentioned by others, having a result in the list of arguments is probably your best bet:

int connected( std::vector<int> & result, std::vector<int> const & store, ...)
{
   int component_size = 0;

   // code

   return component_size;
}

Also, wouldn't component_size == result.size() be true? If so, you should not return anything because it's going to be more confusing.

That simplifies the function to this point:

void connected( std::vector<int> & result, std::vector<int> const & store, ...)
{
   // code
}
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156