Next generation of std::tie - c++

When a function need to return two parameters you can write it using a std::pair:
std::pair<int, int> f()
{return std::make_pair(1,2);}
And if you want to use it, you can write this:
int one, two;
std::tie(one, two) = f();
The problem with this approach is that you need to define 'one' and 'two' and then assign them to the return value of f(). It would be better if we can write something like
auto {one, two} = f();
I watched a lecture (I don't remember which one, sorry) in which the speaker said that the C++ standard people where trying to do something like that. I think this lecture is from 2 years ago. Does anyone know if right now (in almost c++17) you can do it or something similar?

Yes, there is something called structured bindings that allows for multiple values to be initialized in that way.
The syntax uses square brackets however:
#include <utility>
std::pair<int, int> f()
{
//return std::make_pair(1, 2); // also works, but more verbose
return { 1, 2 };
}
int main()
{
auto[one, two] = f();
}
demo

Related

Is it possible / advisable to return a range?

I'm using the ranges library to help filer data in my classes, like this:
class MyClass
{
public:
MyClass(std::vector<int> v) : vec(v) {}
std::vector<int> getEvens() const
{
auto evens = vec | ranges::views::filter([](int i) { return ! (i % 2); });
return std::vector<int>(evens.begin(), evens.end());
}
private:
std::vector<int> vec;
};
In this case, a new vector is constructed in the getEvents() function. To save on this overhead, I'm wondering if it is possible / advisable to return the range directly from the function?
class MyClass
{
public:
using RangeReturnType = ???;
MyClass(std::vector<int> v) : vec(v) {}
RangeReturnType getEvens() const
{
auto evens = vec | ranges::views::filter([](int i) { return ! (i % 2); });
// ...
return evens;
}
private:
std::vector<int> vec;
};
If it is possible, are there any lifetime considerations that I need to take into account?
I am also interested to know if it is possible / advisable to pass a range in as an argument, or to store it as a member variable. Or is the ranges library more intended for use within the scope of a single function?
This was asked in op's comment section, but I think I will respond it in the answer section:
The Ranges library seems promising, but I'm a little apprehensive about this returning auto.
Remember that even with the addition of auto, C++ is a strongly typed language. In your case, since you are returning evens, then the return type will be the same type of evens. (technically it will be the value type of evens, but evens was a value type anyways)
In fact, you probably really don't want to type out the return type manually: std::ranges::filter_view<std::ranges::ref_view<const std::vector<int>>, MyClass::getEvens() const::<decltype([](int i) {return ! (i % 2);})>> (141 characters)
As mentioned by #Caleth in the comment, in fact, this wouldn't work either as evens was a lambda defined inside the function, and the type of two different lambdas will be different even if they were basically the same, so there's literally no way of getting the full return type here.
While there might be debates on whether to use auto or not in different cases, but I believe most people would just use auto here. Plus your evens was declared with auto too, typing the type out would just make it less readable here.
So what are my options if I want to access a subset (for instance even numbers)? Are there any other approaches I should be considering, with or without the Ranges library?
Depends on how you would access the returned data and the type of the data, you might consider returning std::vector<T*>.
views are really supposed to be viewed from start to end. While you could use views::drop and views::take to limit to a single element, it doesn't provide a subscript operator (yet).
There will also be computational differences. vector need to be computed beforehand, where views are computed while iterating. So when you do:
for(auto i : myObject.getEven())
{
std::cout << i;
}
Under the hood, it is basically doing:
for(auto i : myObject.vec)
{
if(!(i % 2)) std::cout << i;
}
Depends on the amount of data, and the complexity of computations, views might be a lot faster, or about the same as the vector method. Plus you can easily apply multiple filters on the same range without iterating through the data multiple times.
In the end, you can always store the view in a vector:
std::vector<int> vec2(evens.begin(), evens.end());
So my suggestions is, if you have the ranges library, then you should use it.
If not, then vector<T>, vector<T*>, vector<index> depending on the size and copiability of T.
There's no restrictions on the usage of components of the STL in the standard. Of course, there are best practices (eg, string_view instead of string const &).
In this case, I can foresee no problems with handling the view return type directly. That said, the best practices are yet to be decided on since the standard is so new and no compiler has a complete implementation yet.
You're fine to go with the following, in my opinion:
class MyClass
{
public:
MyClass(std::vector<int> v) : vec(std::move(v)) {}
auto getEvens() const
{
return vec | ranges::views::filter([](int i) { return ! (i % 2); });
}
private:
std::vector<int> vec;
};
As you can see here, a range is just something on which you can call begin and end. Nothing more than that.
For instance, you can use the result of begin(range), which is an iterator, to traverse the range, using the ++ operator to advance it.
In general, looking back at the concept I linked above, you can use a range whenever the conext code only requires to be able to call begin and end on it.
Whether this is advisable or enough depends on what you need to do with it. Clearly, if your intention is to pass evens to a function which expects a std::vector (for instance it's a function you cannot change, and it calls .push_back on the entity we are talking about), you clearly have to make a std::vector out of filter's output, which I'd do via
auto evens = vec | ranges::views::filter(whatever) | ranges::to_vector;
but if all the function which you pass evens to does is to loop on it, then
return vec | ranges::views::filter(whatever);
is just fine.
As regards life time considerations, a view is to a range of values what a pointer is to the pointed-to entity: if the latter is destroied, the former will be dangling, and making improper use of it will be undefined behavior. This is an erroneous program:
#include <iostream>
#include <range/v3/view/filter.hpp>
#include <string>
using namespace ranges;
using namespace ranges::views;
auto f() {
// a local vector here
std::vector<std::string> vec{"zero","one","two","three","four","five"};
// return a view on the local vecotor
return vec | filter([](auto){ return true; });
} // vec is gone ---> the view returned is dangling
int main()
{
// the following throws std::bad_alloc for me
for (auto i : f()) {
std::cout << i << std::endl;
}
}
You can use ranges::any_view as a type erasure mechanism for any range or combination of ranges.
ranges::any_view<int> getEvens() const
{
return vec | ranges::views::filter([](int i) { return ! (i % 2); });
}
I cannot see any equivalent of this in the STL ranges library; please edit the answer if you can.
EDIT: The problem with ranges::any_view is that it is very slow and inefficient. See https://github.com/ericniebler/range-v3/issues/714.
It is desirable to declare a function returning a range in a header and define it in a cpp file
for compilation firewalls (compilation speed)
stop the language server from going crazy
for better factoring of the code
However, there are complications that make it not advisable:
How to get type of a view?
If defining it in a header is fine, use auto
If performance is not a issue, I would recommend ranges::any_view
Otherwise I'd say it is not advisable.

C++11, copying just one field into a vector

Say I have the following struct in C++
struct Foo {
double a;
int b;
};
And say I have a parameter to some function declared as follows:
const std::initializer_list<Foo> &args;
Is there an concise way to extract just one field from the elements in args to get, for instance, just an std::vector containing each b field from the original args list?
Of course, I know I could do this by just explicitly writing it out as a loop:
std::vector<int> result;
for(auto &x:args) {
result.push_back(x.b);
}
... but given that I can copy an entire initializer_list of any type to a like-typed vector in a single line of C++, just using functions like std::copy and std::back_inserter, I am wondering if there is a more elegant way to do this as well, using stl or C++11 facilities that may already exist.
You could use std::transform and add elements to the vector via std::back_inserter:
std::transform(std::begin(args), std::end(args), std::back_inserter(result),
[] (const Foo & foo) { return foo.b; });
If you find the lambda too verbose you can use std::mem_fn instead (credit goes to #StoryTeller).
std::transform(std::begin(args), std::end(args), std::back_inserter(result), std::mem_fn(&Foo::b));
But then again, your approach isn't necessary bad since it's pretty readable and does the job just fine (might have some performance issues tho).
One solution can be using linq++ like the following:
shared_ptr<vector<Foo>> foo_list;
// suppose foo_list is being filled
shared_ptr<vector> bs = from(foo_list).select(&_1 ->* &Foo::b).get();

Mapping combination of 4 integers to a single value

I have 4 separate integers that need to be mapped to an arbitrary, constant value.
For example, 4,2,1,1 will map to the number 42
And the number 4,2,1,2 will map to the number 86.
Is there anyway I can achieve this by using #define's or some sort of std::map. The concept seems very simple but for some reason I can't think of a good, efficient method of doing it. The methods I have tried are not working so I'm looking for some guidence on implementation of this.
Will a simple function suffice?
int get_magic_number( int a, int b , int c, int d)
{
if( (a==4)&&(b==2)&&(c==1)&&(d==1) ) return 42;
if( (a==4)&&(b==2)&&(c==1)&&(d==2) ) return 86;
...
throw SomeKindOfError();
}
Now that may look ugly, but you can easily create a macro to pretty it up. (Or a helper class or whatever... I'll just show the macro as I think its easy.
int get_magic_number( int a, int b , int c, int d)
{
#DEFINE MAGIC(A,B,C,D,X) if((a==(A))&&(b==(B))&&(c==(C))&&(d==(D))) return (X);
MAGIC(4,2,1,1, 42);
MAGIC(4,2,1,2, 86);
...
#UNDEF MAGIC
throw SomeKindOfError();
}
If you really care you can probably craft a constexpr version of this too, which you'll never be able to do with std::map based solutions.
Utilize a std::map<std::vector<int>, int>, so that the vector containing {4,2,1,1} will have the value 42, and so on.
Edit: I agree std::tuple would be a better way to go if you have a compiler with C++11 support. I used a std::vector because it is arguably more portable at this stage. You could also use a std::array<int, 4>.
If you do not have access to boost::tuple, std::tuple or std::array, you can implement a type holding 4 integers with a suitable less-than comparison satisfying strict weak ordering:
struct FourInts {
int a,b,c,d;
FourInts() : a(), b(), c(), d() {}
bool operator<(const FourInts& rhs) const {
// implement less-than comparison here
}
};
then use an std::map:
std::map<FourInts, int> m;
If you organise your ints in an array of standard library container, you can use std::lexicographical_compare for the less-than comparison.
If you know there's always 4 integers mapped to 1 integer I suggest you go with:
std::map< boost::tuple<int, int, int, int>, int >
Comparison (lexicographical) is already defined for tuples.

How to return more than one value from a C++ function?

I am interested if I can return more then one value from a function. For example consider such a function: extended euclidean algorithm. The basic step is described by this
Input is nonnegative integers a and b;
output is a triplet (d,i,j) such that d=gcd(a,b)=i*a+j*b.
Just to clarify my question's goal I will write a short recursive code:
if (b==0) return (a,1,0)
q=a mod b;
let r be such that a=r*b+q;
(d,k,l)=extendedeuclidean(b,q);
return (d,l,k-l*r);
How does one return a triplet?
You could create a std::tuple or boost::tuple (if you don't use C++0x) from your triple pair and return that.
As has been suggested by Tony The Tiger you can use tuple. It is included in C++11 standard and new compilers already support it. It is also implemented in boost.
For my ibm xlC compiler tuple is in std::tr1 namespace (tried it for MSVC10 — it's in std namespace).
#include <cstdio>
#include <tuple>
// for MSVC
using namespace std;
// for xlC
//using namespace std::tr1;
// for boost
// using namespace boost;
typedef tuple<int, float, char> MyTuple;
MyTuple f() {
return MyTuple(1, 2.0f, '3');
}
int main() {
MyTuple t = f();
printf("%i, %f, %c\n", get<0>(t), get<1>(t), get<2>(t));
}
xlC compilation for TR1:
xlC -D__IBMCPP_TR1__ file.cpp
xlC compilation for boost:
xlC file.cpp -I/path/to/boost/root
Just create an appropriate data structure holding the three values and return that.
struct extmod_t {
int d;
int i;
int j
extmod_t(int d, int i, int j) : d(d), i(i), j(j) { }
};
…
extmod_t result = extendedeuclidean(b, q);
return extmod_t(result.d, l, k - l * r);
Either create a class that encapsulates the triplet and then return the instance of this class, or use 3 by-reference parameters.
I usually find that when I need to return two parameters from a function, it is useful to use the STL std::pair.
You could always stack the pairs inside one another (e.g. std::pair <int, std::pair <int, int> >) and help your self with typedef-s or defines to make it more accessible, but when ever I try doing this my code ends up messy and unpractical for re-use.
For more than two parameters, however, I recommend making you own specific data structure that holds the information you need (if you are returning multiple values there's a high likelihood that they are strongly logically connected somehow and that you might end up using the same structure again).
E.g. I needed a function that returned the slope of the line (1 param) and that was fine. Then I needed to expand it to return both parameters of the parametric representation of the line (y = k*x + l). Two parameters, still fine. Then I remembered that the line can be vertical and that I should add another parameter to indicate that (no parametric representation then)... At this point, it became too complicated to try and make do with existing datatypes, so I typed up my own Line structure and ended up using the same structure all over my project later.

Literate Coding Vs. std::pair, solutions?

As most programmers I admire and try to follow the principles of Literate programming, but in C++ I routinely find myself using std::pair, for a gazillion common tasks. But std::pair is, IMHO, a vile enemy of literate programming...
My point is when I come back to code I've written a day or two ago, and I see manipulations of a std::pair (typically as an iterator) I wonder to myself "what did iter->first and iter->second mean???".
I'm guessing others have the same doubts when looking at their std::pair code, so I was wondering, has anyone come up with some good solutions to recover literacy when using std::pair?
std::pair is a good way to make a "local" and essentially anonymous type with essentially anonymous columns; if you're using a certain pair over so large a lexical space that you need to name the type and columns, I'd use a plain struct instead.
How about this:
struct MyPair : public std::pair < int, std::string >
{
const int& keyInt() { return first; }
void keyInt( const int& keyInt ) { first = keyInt; }
const std::string& valueString() { return second; }
void valueString( const std::string& valueString ) { second = valueString; }
};
It's a bit verbose, however using this in your code might make things a little easier to read, eg:
std::vector < MyPair > listPairs;
std::vector < MyPair >::iterator iterPair( listPairs.begin() );
if ( iterPair->keyInt() == 123 )
iterPair->valueString( "hello" );
Other than this, I can't see any silver bullet that's going to make things much clearer.
typedef std::pair<bool, int> IsPresent_Value;
typedef std::pair<double, int> Price_Quantity;
...you get the point.
You can create two pairs of getters (const and non) that will merely return a reference to first and second, but will be much more readable. For instance:
string& GetField(pair& p) { return p.first; }
int& GetValue(pair& p) { return p.second; }
Will let you get the field and value members from a given pair without having to remember which member holds what.
If you expect to use this a lot, you could also create a macro that will generate those getters for you, given the names and types: MAKE_PAIR_GETTERS(Field, string, Value, int) or so. Making the getters straightforward will probably allow the compiler to optimize them away, so they'll add no overhead at runtime; and using the macro will make it a snap to create those getters for whatever use you make of pairs.
You could use boost tuples, but they don't really alter the underlying issue: Do your really want to access each part of the pair/tuple with a small integral type, or do you want more 'literate' code. See this question I posted a while back.
However, boost::optional is a useful tool which I've found replaces quite a few of the cases where pairs/tuples are touted as ther answer.
Recently I've found myself using boost::tuple as a replacement for std::pair. You can define enumerators for each member and so it's obvious what each member is:
typedef boost::tuple<int, int> KeyValueTuple;
enum {
KEY
, VALUE
};
void foo (KeyValueTuple & p) {
p.get<KEY> () = 0;
p.get<VALUE> () = 0;
}
void bar (int key, int value)
{
foo (boost:tie (key, value));
}
BTW, comments welcome on if there is a hidden cost to using this approach.
EDIT: Remove names from global scope.
Just a quick comment regarding global namespace. In general I would use:
struct KeyValueTraits
{
typedef boost::tuple<int, int> Type;
enum {
KEY
, VALUE
};
};
void foo (KeyValueTuple::Type & p) {
p.get<KeyValueTuple::KEY> () = 0;
p.get<KeyValueTuple::VALUE> () = 0;
}
It does look to be the case that boost::fusion does tie the identity and value closer together.
As Alex mentioned, std::pair is very convenient but when it gets confusing create a structure and use it in the same way, have a look at std::pair code, it's not that complex.
I don't like std::pair as used in std::map either, map entries should have had members key and value.
I even used boost::MIC to avoid this. However, boost::MIC also comes with a cost.
Also, returning a std::pair results in less than readable code:
if (cntnr.insert(newEntry).second) { ... }
???
I also found that std::pair is commonly used by the lazy programmers who needed 2 values but didn't think why these values where needed together.