I want to be able to write in C++ something similar to the following Python code:
if x in [1, 2, 3, 5] ...
to test whether an element is contained in a set of hard-coded values, defined in-place. Like this:
if (in(x, {1, 2, 3, 5})) ...
Here is the possible implementation of the in function:
template<class T>
bool in(const T& x, std::initializer_list<T> c)
{
return std::find(c.begin(), c.end(), x) != c.end();
}
My question is: do I really have to write this function by myself? Are there any default implementations over there? Maybe in boost? I checked boost::contains, but it works only with strings.
If you have access to c++20 you can use set's contains which returns a bool allowing you to do:
if(set{ 4, 8, 15, 16, 23, 42 }.contains(x))
Live Example
Otherwise, with just c++11 you can still use set's count which only returns 1 or 0 allowing you to do something like:
if(set<int>{ 4, 8, 15, 16, 23, 42 }.count(x) > 0U)
Live Example
Keep in mind that magic numbers can be confusing for your audience (and cause 5 seasons of Lost.)
I'd recommend declaring your numbers as a const initializer_list<int> and giving them a meaningful name:
const auto finalCandidates{ 4, 8, 15, 16, 23, 42 };
if(cend(finalCandidates) != find(cbegin(finalCandidates), cend(finalCandidates), x))
boost::algorithm::contains doesn't only work on strings, it works on any range, i.e. a sequence that can yield a begin and end iterator. To find a single value use it as follows:
auto l = {1,2,3,4};
auto l1 = {2}; // thing you want to find
if(boost::algorithm::contains(l, l1)) { ... }
You can perform your search using the standard library only, but doing so is quite a bit more verbose. A couple of options are:
using a lambda
if(std::any_of(l.begin(), l.end(),
[](int i){ return i == 2; })) { ... }
using std::bind
using std::placeholders::_1;
if(std::any_of(l.begin(), l.end(),
std::bind(std::equal_to<>(), 2, _1)) { ... }
Live demo
Note that std::equal_to<>() is a C++14-only option. For a C++11 compiler, use std::equal_to<int>().
Indeed the STL does not have a simple std::contains() function. Recently, there was a discussion on reddit about this topic.
Unfortunately, what came out of this is that it is considered harmful to have std::contains(), since it encourages people to write slow algorithms. Think for instance of
if (!std::contains(my_set.begin(), my_set.end(), entry)) {
my_set.insert(entry);
}
This code example essentially searches for the correct position twice: Once in contains, and once to find the insert location.
In my opinion, it would still be very helpful to have std::contains(), but so far no one was convinced yet to write a proposal.
So either use boost (as suggested by other in this thread), or write your own function which you essentially already did :-)
Related
As we know that in c++20 pipe operator | stands for function composition but here in below code we are passing one container and one algorithm so how is it working and how we are able to pass different container types to same function?
int main()
{
std::vector<int> vnumbers = {1, 2, 3, 4, 5, 6};
std::list<int> lnumbers = {6, 5, 4, 3, 2, 1};
auto vresults = vnumbers | std::views::filter([](int n){ return n % 3 == 0; });
auto lresults = lnumbers | std::views::filter([](int n){ return n % 3 == 0; });
for (auto e:vresults)
{
std::cout<<"V:"<<e<<std::endl;
}
for (auto e:lresults)
{
std::cout<<"L:"<<e<<std::endl;
}
}
As we know that in c++20 pipe operator | stands for function composition but here in below code we are passing one container and one algorithm so how is it working
Saying that | stands for function composition is a bit inaccurate, exactly for the reason you mention in your question: function composition allows composing functions together, in line with the mathematical definition.
On the other hand, when we don't want to be too pedantic, we can accept that composing functions means "using them with a nice syntax that allows piping a single flow of data through many of them". That's kind of what Range-v3 and <ranges> allows. Writing this
auto out = in | filter(f) | tranform(g) | take(n) | drop(m);
means the same as this (modulo I've not tested, probably the arguments go the other way around, I don't rememeber, as I always use the | syntax)
auto out = drop(take(transform(filter(in, f), g), n), m);
which means that you are applying to in the composition of 4 functions. BUT those 4 functions are not filter, transform, take, and drop, but rather those 4 functions with their second argument bound to f, g, n, and m respectively.
Boost.Hana does offer a function composition function called boost::hana::compose.
Notice that functions with their second argument bound to refers to what is known as "partial function application", and Boost.Hana also gives you that, via boost::hana::partial and boost::hana::reverse_partial.
how we are able to pass different container types to same function?
Well, we are in C++ and we have templates, so passing objects of different types to the same "function" (well, function template) shouldn't scare us. In the context of ranges, all those functions/function objects filter, transform, and so on, expect a range, i.e. something on which begin and end can be called, so both std::vector and std::list comply with the requirement.
I want to rotate a subset of an vector inside the whole vector. The subset to be rotated is defined by another vector.
What I want to achieve is this:
template<typename CONTAINER>
void rotateSubset(CONTAINER& whole, const CONTAINER& subset)
{
// ???
}
auto whole = std::vector<int> {1, 2, 3, 4, 5};
auto part = std::vector<int> { 2, 3, 4 };
auto part2 = std::vector<int> {1, 5};
rotateSubset(whole, part);
// whole is now 1, 3, 4, 2, 5;
rotateSubset(whole, part2);
// whole is now 5, 3, 4, 2, 1
The given subset is guaranteed to be contained by the larger whole set. The subset could be any subset of the whole, in any order; it need not be contiguous.
This is what I've tried so far:
template<typename CONTAINER>
void rotateSubset(CONTAINER& whole, const CONTAINER& subset)
{
assert(subset.isSubsetOf(whole)); // don't worry about the implementation of this pseudo-code for now
std::rotate(subset.begin(), subset.end());
if (subset.size() == whole.size())
whole = subset;
else
{
// copy the subset vector into the whole vector in the new order
auto it = subset.cbegin();
for (auto& element : whole)
if (std::find(subset.cbegin(), subset.cend(), element) != subset.cend())
element = *it++;
}
}
This works, however it feels a bit sketchy to me. I was wondering if there was some neat way of using the Ranges library in C++20 to do it. Something like this:
// PSEUDO-CODE
auto subRange = std::ranges::views::subset(whole, part);
std::rotate(subRange.begin(), subRange.end());
I don't have a good knowledge of the Ranges library yet, but I think that something like this should be possible.
Please note: I want the solution to use a simple std::rotate() at some level. The reason for this is that I want to perform other similar functions on a sub-set as well (i.e. std::shuffle()), so the actual function that does the rotation / shuffling / whatever will be a variable in the final version. It's the "altering a subset" part that I'm really interested in here; the rest will come together later.
Could someone please give a complete (including all header files) working (that compiles) example of how to use Boost BCCL on a for example a boost::RandomAccessContainer together with std::sort?
What’s wrong with the example given in the documentation?
Granted, it’s not complete but it should be trivial to get it to compile …
Furthermore, Your request cannot be fulfilled: you want concept checking for std::sort, but this function cannot be re-defined. You could of course define your own sorting function, and use the BCCL code provided by the documentation:
#include <algorithm>
#include "boost/concept/requires.hpp"
template<typename I>
BOOST_CONCEPT_REQUIRES(
((Mutable_RandomAccessIterator<I>))
((LessThanComparable<typename Mutable_RandomAccessIterator<I>::value_type>)),
(void)) // return type
sort(I begin, I end)
{
std::sort(begin, end);
}
int main() {
int a[] = { 1, 4, 3, 2, 6, 5 };
sort(a, a + 6);
}
Note: I have never used the BCCL. Hacking the above together was trivial and took me less than five minutes. Certainly you could have done the same?
How can I combine several functors to generate a isOdd functor?
equal_to
modulus
bind2nd
...
int nums[] = {0, 1, 2, 3, 4};
vector<int> v1(nums, nums+5), v2;
remove_copy_if(v1.begin(), v1.end(), back_inserter(v2), isOdd);
v2 => {0, 2, 4}
Using just the primitives provided in the standard libraries, this is actually surprisingly difficult because the binders provided by bind1st and bind2nd don't allow you to compose functions. In this particular case, you're trying to check if
x % 2 == 1
Which, if you consider how the <functional> primitives work, is equivalent to
equal_to(modulus(x, 2), 1)
The problem is that the components in <functional> don't allow you to pass the output of one function as the input to another function very easily. Instead, you'll have to rely on some other technique. In this case, you could cheat by using two successive applications of not1:
not1(not1(bind2nd(modulus<int>(), 2)))
This works because it's equivalent to
!!(x % 2)
If x is even, then this is !!0, which is false, and if x is odd this is !!1, which is true. The reason for the double-filtering through not1 is to ensure that the result has type bool rather than int, since
bind2nd(modulus<int>(), 2)
is a function that produces an int rather than the bool you want.
isOdd can be defined as:
bind2nd(modulus<int>(),2)
It's very annoying that copy_if is not in C++. Does anyone know if it will be in C++0x?
Since the C++0x is not yet finalized, you can only take a look at the most recent draft.
In the meantime, it's not very hard to make your own copy_if() using remove_copy_if():
#include <functional>
struct my_predicate : std::unary_function<my_arg_type, bool> {
bool operator()(my_arg_type const& x) const { ... }
};
// To perform "copy_if(x, y, z, my_predicate())", write:
remove_copy_if(x, y, z, std::not1(my_predicate()));
Using not1() requires your predicate class to supply a nested type, argument_type, identifying the type of the argument -- as shown above, one convenient way to do this is to derive from unary_function<T, U>, where T is the argument type.
Just for completeness, in case someone googles his/her way to this question, it should be mentioned that now (in C++11 and later) there is a copy if algorithm. It behaves as expected (copies the elements in a range, for which some predicate returns true, to another range).
A typical use case would be
std::vector<int> foo{ 25, 15, 5, -5, -15 };
std::vector<int> bar;
// copy only positive numbers:
auto it = std::copy_if (foo.begin(), foo.end(), std::back_inserter(bar),
[](int i){return !(i<0);
});