Difference between revisions of "cpp/iterator/projected"
Andreas Krug (Talk | contribs) m (headers sorted) |
m (fmt.) |
||
(2 intermediate revisions by 2 users not shown) | |||
Line 7: | Line 7: | ||
template< std::indirectly_readable I, | template< std::indirectly_readable I, | ||
std::indirectly_regular_unary_invocable<I> Proj > | std::indirectly_regular_unary_invocable<I> Proj > | ||
− | struct projected { | + | struct projected |
+ | { | ||
using value_type = std::remove_cvref_t<std::indirect_result_t<Proj&, I>>; | using value_type = std::remove_cvref_t<std::indirect_result_t<Proj&, I>>; | ||
std::indirect_result_t<Proj&, I> operator*() const; // not defined | std::indirect_result_t<Proj&, I> operator*() const; // not defined | ||
Line 14: | Line 15: | ||
template< std::indirectly_readable I, | template< std::indirectly_readable I, | ||
std::indirectly_regular_unary_invocable<I> Proj > | std::indirectly_regular_unary_invocable<I> Proj > | ||
− | using projected = /*projected-impl*/<I, Proj>:: | + | using projected = /*projected-impl*/<I, Proj>::/*__type*/; // see (3) |
}} | }} | ||
{{dcl|num=2|since=c++20|until=c++26|1= | {{dcl|num=2|since=c++20|until=c++26|1= | ||
template< std::weakly_incrementable I, class Proj > | template< std::weakly_incrementable I, class Proj > | ||
− | struct incrementable_traits<std::projected<I, Proj>> { | + | struct incrementable_traits<std::projected<I, Proj>> |
+ | { | ||
using difference_type = std::iter_difference_t<I>; | using difference_type = std::iter_difference_t<I>; | ||
}; | }; | ||
}} | }} | ||
− | {{dcl|num=3|since=c++26|1= | + | {{dcl|num=3|since=c++26|notes={{mark expos}}|1= |
template< class I, class Proj > | template< class I, class Proj > | ||
− | struct /*projected-impl*/ { // | + | struct /*projected-impl*/ |
− | + | { | |
+ | struct /*__type*/ | ||
+ | { | ||
using value_type = std::remove_cvref_t<std::indirect_result_t<Proj&, I>>; | using value_type = std::remove_cvref_t<std::indirect_result_t<Proj&, I>>; | ||
using difference_type = std::iter_difference_t<I>; // conditionally present | using difference_type = std::iter_difference_t<I>; // conditionally present | ||
Line 53: | Line 57: | ||
===Example=== | ===Example=== | ||
− | {{example|code= | + | {{example |
+ | |code= | ||
#include <algorithm> | #include <algorithm> | ||
#include <cassert> | #include <cassert> | ||
Line 59: | Line 64: | ||
#include <iterator> | #include <iterator> | ||
− | template<class T> struct Holder { T t; }; | + | template<class T> |
+ | struct Holder | ||
+ | { | ||
+ | T t; | ||
+ | }; | ||
struct Incomplete; | struct Incomplete; | ||
− | using | + | using P = Holder<Incomplete>*; |
− | static_assert(std::equality_comparable< | + | static_assert(std::equality_comparable<P>); // OK |
− | static_assert(std::indirectly_comparable< | + | static_assert(std::indirectly_comparable<P*, P*, std::equal_to<>>); // Error before C++26 |
− | static_assert(std::sortable< | + | static_assert(std::sortable<P*>); // Error before C++26 |
int main() | int main() | ||
{ | { | ||
− | + | P a[10] = {}; // ten null pointers | |
assert(std::count(a, a + 10, nullptr) == 10); // OK | assert(std::count(a, a + 10, nullptr) == 10); // OK | ||
assert(std::ranges::count(a, a + 10, nullptr) == 10); // Error before C++26 | assert(std::ranges::count(a, a + 10, nullptr) == 10); // Error before C++26 | ||
} | } | ||
}} | }} | ||
+ | |||
+ | ===See also=== | ||
+ | {{dsc begin}} | ||
+ | {{dsc inc|cpp/iterator/dsc projected_value_t}} | ||
+ | {{dsc end}} | ||
{{langlinks|es|ja|zh}} | {{langlinks|es|ja|zh}} |
Latest revision as of 14:43, 12 April 2024
Defined in header <iterator>
|
||
(1) | ||
template< std::indirectly_readable I, std::indirectly_regular_unary_invocable<I> Proj > |
(since C++20) (until C++26) |
|
template< std::indirectly_readable I, std::indirectly_regular_unary_invocable<I> Proj > |
(since C++26) | |
template< std::weakly_incrementable I, class Proj > struct incrementable_traits<std::projected<I, Proj>> |
(2) | (since C++20) (until C++26) |
template< class I, class Proj > struct /*projected-impl*/ |
(3) | (since C++26) (exposition only*) |
projected
combines an indirectly_readable
type I
and a callable object type Proj
into a new indirectly_readable
type whose reference type is the result of applying Proj
to the std::iter_reference_t<I>.weakly_incrementable
type when I
is also a weakly_incrementable
type.difference_type
exists only if I
models weakly_incrementable
.projected
is used only to constrain algorithms that accept callable objects and projections, and hence its operator*() is not defined.
Contents |
[edit] Template parameters
I | - | an indirectly readable type |
Proj | - | projection applied to a dereferenced I
|
[edit] Notes
The indirect layer prevents I
and Proj
to be associated classes of projected
. When an associated class of I
or Proj
is an incomplete class type, the indirect layer avoids the unnecessary attempt to inspect the definition of that type that results in hard error.
[edit] Example
#include <algorithm> #include <cassert> #include <functional> #include <iterator> template<class T> struct Holder { T t; }; struct Incomplete; using P = Holder<Incomplete>*; static_assert(std::equality_comparable<P>); // OK static_assert(std::indirectly_comparable<P*, P*, std::equal_to<>>); // Error before C++26 static_assert(std::sortable<P*>); // Error before C++26 int main() { P a[10] = {}; // ten null pointers assert(std::count(a, a + 10, nullptr) == 10); // OK assert(std::ranges::count(a, a + 10, nullptr) == 10); // Error before C++26 }
[edit] See also
(C++26) |
computes the value type of an indirectly_readable type by projection(alias template) |