Why Is There No Transform_If in the C++ Standard Library

Why is there no transform_if in the C++ standard library?

The standard library favours elementary algorithms.

Containers and algorithms should be independent of each other if possible.

Likewise, algorithms that can be composed of existing algorithms are only rarely included, as shorthand.

If you require a transform if, you can trivially write it. If you want it /today/, composing of ready-mades and not incur overhead, you can use a range library that has lazy ranges, such as Boost.Range, e.g.:

v | filtered(arg1 % 2) | transformed(arg1 * arg1 / 7.0)

As @hvd points out in a comment, transform_if double result in a different type (double, in this case). Composition order matters, and with Boost Range you could also write:

 v | transformed(arg1 * arg1 / 7.0) | filtered(arg1 < 2.0)

resulting in different semantics. This drives home the point:

it makes very little sense to include std::filter_and_transform, std::transform_and_filter, std::filter_transform_and_filter etc. etc. into the standard library.

See a sample Live On Coliru

#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>

using namespace boost::adaptors;

// only for succinct predicates without lambdas
#include <boost/phoenix.hpp>
using namespace boost::phoenix::arg_names;

// for demo
#include <iostream>

int main()
{
std::vector<int> const v { 1,2,3,4,5 };

boost::copy(
v | filtered(arg1 % 2) | transformed(arg1 * arg1 / 7.0),
std::ostream_iterator<double>(std::cout, "\n"));
}

Why is operator!= removed in C++20 for many standard library types?

In C++20 the way that the relational operators work was changed, notably with the introduction of the spaceship <=> operator. In particular, If you only provide operator==, then a != b is rewritten to !(a == b).

From [over.match.oper]/3.4:

The rewritten candidate set is determined as follows:

  • For the relational ([expr.rel]) operators, the rewritten candidates include all non-rewritten candidates for the expression x <=> y.
  • For the relational ([expr.rel]) and three-way comparison ([expr.spaceship]) operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each non-rewritten candidate for the expression y <=> x.
  • For the != operator ([expr.eq]), the rewritten candidates include all non-rewritten candidates for the expression x == y.
  • For the equality operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each non-rewritten candidate for the expression y == x.
  • For all other operators, the rewritten candidate set is empty.

And [over.match.oper]/9:

If a rewritten operator== candidate is selected by overload resolution for an operator @, its return type shall be cv bool, and x @ y is interpreted as:

  • if @ is != and the selected candidate is a synthesized candidate with reversed order of parameters, !(y == x),
  • otherwise, if @ is !=, !(x == y),
  • otherwise (when @ is ==), y == x,

in each case using the selected rewritten operator== candidate.

As such, an explicit overload for operator!= is no longer necessary. The removal of the operator has not changed comparison semantics.

All containers have had their operator!= removed, as far as I can tell (check e.g. the vector synopsis). The only exceptions are the container adaptors std::queue and std::stack: my guess is that it is to preserve backwards compatibility when used with third-party containers, in case the equality operators are not symmetric.

Is there a list of c++11 standard library interfaces which require exceptions enabled?

This question is over one month old, and unanswered.

I am providing an answer which can be considered a community wiki, add to it as needed.

  • std::thread Section 30.2.2. Transitive. Abstraction implemented using native implementations.

  • std::mutex, std::recursive_mutex, std::timed_mutex, std::recursive_timed_mutex. Section 30.4.1, Intransitive if you supply your own exception free locking (via BasicLockable, Lockable, TimedLockable). Abstraction implemented using native implementations.

  • std::condition_variable Section 30.5. Transitive. Abstraction implemented using native implementations.

note: There will be more.

Why is the C++ standard library aligning large string buffers to 32 bytes?

While I don't know the official reason your compiler/library behaves this way, I can certainly see an immediate benefit: SIMD.

Single Instruction Multiple Data instructions are operations that allow you to get very cheap parallelism. However, they do have some requirements before you, or more likely your compiler, can make use of them effectively.

One of those requirements is that loading memory in SIMD registers requires that the memory being loaded be more strictly aligned than for regular single-value operations.

Large buffers like that are very often used in algorithms that can make use of these instructions, and tend to see bigger benefits than smaller ones.

Also, since the buffer is already fairly large, the "waste" is proportionally very small. Wasting a small amount of memory to ensure that computations can be done 4* times faster sure sounds like a reasonable tradeoff to me.

N.B. It's not actually 4 times. Auto-vectorized loops typically have a prefix and postfix section to deal with misaligned data, so the real gain is just skipping the prefix and jumping straight to the vectorized loop. But these technicalities don't really matter as far as your question goes.

Where is the standard library predefined 'user-defined' literal m defined?

It is not a standard user defined literal

The list of standard user defined literals can be found here at the bottom: http://en.cppreference.com/w/cpp/language/user_literal

And operator""m is not one of them, as the standard library does not deal with units of length (yet).

Does there exist a type level left-fold metafunction in the standard library?

I think this one basically has to be recursive. There is no such thing in the standard library, and for once I can't come up with a Boost.Mp11 one-liner.

namespace impl {
template <typename T>
struct unfold_t {
using type = std::tuple<T>;
};

template <typename A, typename B>
struct unfold_t<std::pair<A, B>> {
using type = mp_push_back<typename unfold_t<A>::type, B>;
};
}

template <typename T>
using unfold = typename impl::unfold_t<T>::type;

With an assist from T.C., the newest edition of Mp11 (1.73) has an algorithm named mp_iterate which we can use thusly.

Given std::pair<std::pair<X, Y>, Z>, if we apply mp_first repeatedly (as R) we get the sequence:

  • std::pair<std::pair<X, Y>, Z>
  • std::pair<X, Y>
  • X

Then, if we apply mp_second to that sequence, we get:

  • Z
  • Y
  • ill-formed

That's pretty close. We do need that X. So we need a more complex metafunction for F: we need to get the second value if possible. There's a metafunction for that:

template <typename L>
using second_or_self = mp_eval_or<L, mp_second, L>;

And now mp_iterate<T, second_or_self, mp_first> gives us mp_list<Z, Y, X>. All we need to do at that point is reverse it and turn it into a std::tuple:

template <typename L>
using unfold = mp_rename<mp_reverse<
mp_iterate<L, second_or_self, mp_first>>,
std::tuple>;

Now that Boost.173 is on compiler-explorer, demo.


Or, I suppose, if you really hate your readers, you can make this a single alias:

template <typename L>
using unfold = mp_rename<mp_reverse<
mp_iterate_q<L,
mp_bind<mp_eval_or_q, _1, mp_quote<mp_second>, _1>,
mp_quote<mp_first>>>,
std::tuple>;

How to include all of the C++ Standard Library at once?

On some compilers, including <bits/stdc++.h> might do what you're looking for.

Note however that it makes your code nonportable (it may not work on other compilers, or even different versions of the same compiler). This is ok in some cases.

More info about why doing this might not be a good idea: Why should I not #include <bits/stdc++.h>?



Related Topics



Leave a reply



Submit