How to return multiple values (vector and one int value) through function - c++14

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);

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);

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
}

Related

Function taking std::initializer_list

I came across a function a colleague had written that accepted an initializer list of std::vectors. I have simplified the code for demonstration:
int sum(const std::initializer_list<std::vector<int>> list)
{
int tot = 0;
for (auto &v : list)
{
tot += v.size();
}
return tot;
}
Such a function would allow you call the function like this with the curly braces for the initializer list:
std::vector<int> v1(50, 1);
std::vector<int> v2(75, 2);
int sum1 = sum({ v1, v2 });
That looks neat but doesn't this involve copying the vectors to create the initializer list? Wouldn't it be more efficient to have a function that takes a vector or vectors? That would involve less copying since you can move the vectors. Something like this:
int sum(const std::vector<std::vector<int>> &list)
{
int tot = 0;
for (auto &v : list)
{
tot += v.size();
}
return tot;
}
std::vector<std::vector<int>> vlist;
vlist.reserve(2);
vlist.push_back(std::move(v1));
vlist.push_back(std::move(v2));
int tot = sum2(vlist);
Passing by initializer list could be useful for scalar types like int and float, but I think it should be avoided for types like std::vector to avoid unnecessary copying. Best to use std::initializer_list for constructors as it intended?
That looks neat but doesn't this involve copying the vectors to create the initializer list?
Yes, that is correct.
Wouldn't it be more efficient to have a function that takes a vector or vectors?
If you are willing to move the contents of v1 and v2 to a std::vector<std::vector<int>>, you could do the samething when using std::initializer_list too.
std::vector<int> v1(50, 1);
std::vector<int> v2(75, 2);
int sum1 = sum({ std::move(v1), std::move(v2) });
In other words, you can use either approach to get the same effect.

Variadic Template Recursion

I am trying to use recursion to solve this problem where if i call
decimal<0,0,1>();
i should get the decimal number (4 in this case).
I am trying to use recursion with variadic templates but cannot get it to work.
Here's my code;
template<>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a*2 + decimal<pack...>();
};
int main(int argc, char *argv[]){
cout<<decimal<0,0,1>()<<endl;
return 0;
}
What would be the best way to solve this?
template<typename = void>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a + 2*decimal<pack...>();
};
The problem was with the recursive case, where it expects to be able to call decltype<>(). That is what I have defined in the first overload above. You can essentially ignore the typename=void, the is just necessary to allow the first one to compile.
A possible solution can be the use of a constexpr function (so you can use it's values it's value run-time, when appropriate) where the values are argument of the function.
Something like
#include <iostream>
constexpr int decimal ()
{ return 0; }
template <typename T, typename ... packT>
constexpr int decimal (T const & a, packT ... pack)
{ return a*2 + decimal(pack...); }
int main(int argc, char *argv[])
{
constexpr int val { decimal(0, 0, 1) };
static_assert( val == 2, "!");
std::cout << val << std::endl;
return 0;
}
But I obtain 2, not 4.
Are you sure that your code should return 4?
-- EDIT --
As pointed by aschepler, my example decimal() template function return "eturns twice the sum of its arguments, which is not" what do you want.
Well, with 0, 1, true and false you obtain the same; with other number, you obtain different results.
But you can modify decimal() as follows
template <typename ... packT>
constexpr int decimal (bool a, packT ... pack)
{ return a*2 + decimal(pack...); }
to avoid this problem.
This is a C++14 solution. It is mostly C++11, except for std::integral_sequence nad std::index_sequence, both of which are relatively easy to implement in C++11.
template<bool...bs>
using bools = std::integer_sequence<bool, bs...>;
template<std::uint64_t x>
using uint64 = std::integral_constant< std::uint64_t, x >;
template<std::size_t N>
constexpr uint64< ((std::uint64_t)1) << (std::uint64_t)N > bit{};
template<std::uint64_t... xs>
struct or_bits : uint64<0> {};
template<std::int64_t x0, std::int64_t... xs>
struct or_bits<x0, xs...> : uint64<x0 | or_bits<xs...>{} > {};
template<bool...bs, std::size_t...Is>
constexpr
uint64<
or_bits<
uint64<
bs?bit<Is>:std::uint64_t(0)
>{}...
>{}
>
from_binary( bools<bs...> bits, std::index_sequence<Is...> ) {
(void)bits; // suppress warning
return {};
}
template<bool...bs>
constexpr
auto from_binary( bools<bs...> bits={} )
-> decltype( from_binary( bits, std::make_index_sequence<sizeof...(bs)>{} ) )
{ return {}; }
It generates the resulting value as a type with a constexpr conversion to scalar. This is slightly more powerful than a constexpr function in its "compile-time-ness".
It assumes that the first bit is the most significant bit in the list.
You can use from_binary<1,0,1>() or from_binary( bools<1,0,1>{} ).
Live example.
This particular style of type-based programming results in code that does all of its work in its signature. The bodies consist of return {};.

Why does the sort not work?

the error is:
/usr/include/c++/4.8/bits/stl_algo.h:2159:29: error: invalid conversion from 'int' to 'const char*' [-fpermissive]
if (__comp(*__i, *__first))
I am passing 2 strings X and Y. Now the sort should compare XY and YX and then return the X if XY>YX or return Y. X and Y will have values like - 33 or 9999.
string Solution::largestNumber(const vector<int> &A) {
int i,n;
vector<string> B;
string str;
for(i=0; i<A.size(); i++)
{
B[i]=to_string(A[i]);
}
sort(A.begin(), A.end(),[](const string lhs, const string rhs){
return rhs+lhs < lhs+rhs;
});
for(i=0; i<A.size(); i++)
{
str+= to_string(A[i]);
}
return str;}
You are calling std::sort on a range from A which is a std::vector<int>, so the compare function should compare int-s.
You could fill B initially with 0,1, .... A.size()-1 then, given two indexes i1 and i2 to compare, construct the strings and compare them.
the error is: /usr/include/c++/4.8/bits/stl_algo.h:2159:29: error: invalid conversion from 'int' to 'const char*' [-fpermissive] if (__comp(*__i, *__first))
sort(A.begin(), A.end(),[](const string lhs, const string rhs){...});
Your sort comparator is expecting to compare two std::strings. The element type of A is int. You created B to be a conversion of A's elements to B's element type of std::string. Use B.
Other notes:
string Solution::largestNumber(const vector<int> &A) {
int i,n; // n???
// vector<string> B; // B is empty. Calling B[i] will cause a
// segfault for attempting to access memory
// out of bounds.
vector<string> B(A.size()); // Fix: pass in the size. Now creates B
// with size elements that can be accessed.
string str;
// Consider using algorithms like std::transform
for(i=0; i<A.size(); i++)
{
B[i]=to_string(A[i]); // You won't segfault here now.
}
// Corrected your sort.
sort(B.begin(), B.end(),[](const string lhs, const string rhs){
return rhs+lhs < lhs+rhs;
});
// Appending should be done on the sorted string vector. Consider using
// a ranged-based for loop here.
for(i=0; i<B.size(); i++)
{
str+= B[i];
}
return str;
}

remove element from boost::numeric::ublas::vector

If I declare a boost::numeric::ublas::vector aaa and later call the method aaa.erase_element(n), I get a vector with the same size, but with the n-element equal to zero.
Do you know how can I completely remove the element in order to get a lower-size vector?
I can't use std::vector unfortunately...
template<class T> void remove(vector<T> &v, uint idx)
{
assert(idx < v.size());
for (uint i = idx; i < v.size() - 1; i++) {
v[i] = v[i + 1];
}
v.resize(v.size() - 1);
}
Note: this works if T is a primitive type (int, double, etc.) or simple struct. If T is a pointer
type, or contains pointers, then you may need to look after destruction of referenced objects. Or perhaps use ptr_vector.

cant find error in printf function

following is code of function
void printf(char *ch,void *num,...)
{
int i;
va_list ptr; //to store variable length argument list
va_start(ptr,num); // initialise ptr
for(i=0;ch[i]!='\0';i++)
{
if(ch[i]=='%') // check for % sign in print statement
{ i++;
if( ch[i]=='d')
{
int *no = (int *)va_arg(ptr,int * );
int value=*no; // just used for nothing
printno(value); //print int number
}
if( ch[i]=='u')
{
unsigned long *no =(unsigned long *) va_arg(ptr,unsigned long *);
unsigned long value=*no;
printuno(value); //print unsigned long
}
}
else // if not % sign then its regular character so print it
{
printchar(ch[i]);
}
}
}
this my code for printf() to print integer value and uint values
It is working fine for string portion in arguments but for %d %u it shows the same
values for all variables. This value is 405067 - even though the values of the variables are different.
Please tell me how to fix this.
Why are you interpreting the argument as a pointer? I'm surprised you aren't crashing. You should just be using
int num = va_arg(ptr,int);
printno(num);
and
unsigned int num = va_arg(ptr,unsigned int);
printuno(value);
(note, unsigned int, not unsigned long, because that would actually be %lu)
Also, get rid of the num parameter. It's wrong. Your va_list should be initialized as
`va_start(ptr, ch);`
va_start() takes the last argument before the varargs, not the first argument.
As noted in a comment, the C99 prototype for printf() is:
int printf(const char * restrict format, ...);
Therefore, if you're calling your function printf(), you should probably follow its design. I'm going to ignore flags, field width, precision and length modifiers, assuming that the conversion specifiers are simply two characters each, such as %d or %%.
int printf(const char * restrict format, ...)
{
va_list args;
va_start(args, format);
char c;
int len = 0;
while ((c = *format++) != '\0')
{
if (c != '%')
{
putchar(c);
len++;
}
else if ((c = *format++) == '%')
{
putchar(c);
len++;
}
else if (c == 'd')
{
int value = va_arg(args, int);
len += printno(value);
}
else if (c == 'u')
{
unsigned value = va_arg(args, unsigned);
len += printuno(value);
}
else
{
/* Print unrecognized formats verbatim */
putchar('%');
putchar(c);
len += 2;
}
}
return len;
}
Dealing with the full set of format specifiers (especially if you add the POSIX n$ notation as well as flags, field width, precision and length modifiers) is much harder, but this should get you moving in the correct direction. Note that I assume the printno() and printuno() functions both report how many characters were written for the conversion specifier. The function returns the total number of characters written. Note, too, that production code would need to allow for the called functions to fail, and would therefore probably not use the len += printno(value); notation, but would capture the return from printno() into a separate variable that could be tested for an error before adding it to the total length output.

Resources