I know I can do it as follows:
struct split : unary_function<void, pair<int,int> >
{
pair<vector<int>,vector<int> > a;
void operator()(pair<int,int> p) { a.first.push_back(p.first);
a.second.push_back(p.second); }
};
...
vector<pair<int,int> > p;
for (int i = 0; i < 100; i++)
p.push_back(pair<int,int>(i,2*i));
split s = for_each(p.begin(), p.end(), split());
...
But I'm not very satisfied with that solution. It seems that I'll
need to have 3 vectors at the end of the day, 1 of the original, and 2
afterwards.
Is there a better way?
(fyi: I'm trying to write an app for audio data that will split the
interleaved stereo channels into seperate right and left channels.)
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Isn't the instantiation of three vectors at some point in the process
a given when converting from vector<pair<int, int>> to
pair<vector<int>, vector<int> >? The first type requires a vector
(obviously) and the latter two vectors.
Using a data structure that's indexable by channel or sample-set
without copying or conversion would probably be more efficient if
that's an option. A matrix, in effect. Apologies in advance if I'm
misconstruing anything.
Tom
One option would be to drop the std::pair structure of the original
design and just pack everything in a single std::vector<int>.
If you envision your data as a 2xN array, then interleaved would be
packing the data in column major order. Separate channels would just
be row major order. Converting between interleaved and separate
channels can now be accomplished in-place; you won't take the memory
hit of allocating two additional vectors. As an added advantage, this
would also allow for more than 2 audio channels.
Of course, the details of how the channel data is stored would be
hidden inside a pretty class.
- Niek Sanders
http://www.cis.rit.edu/~njs8030/
Um, yes? If I'm not misunderstanding you, that is exactly what you need,
rigth? Or is it just that you don't need the original afterwards? In that
case, I'd say that you are making some premature optimisations.
Anyway, I would write two functors, select_first and select second and then
use std::transform:
// Note: I'm not sure about the parameter ordering here
transform( p.begin(), p.end,
back_inserter(target.first), select_first());
transform( p.begin(), p.end,
back_inserter(target.second), select_second());
> Is there a better way?
Define "better". Anyway, the fastest operation is the one that you don't do,
i.e. if you have settled on an (abstract) interface you simply program it
in a way that doesn't involve shifting data around, i.e. you write a
wrapper that feels like a std::vector but internally operates on the first
or second of a vector of pairs.
Uli
--
Sator Laser GmbH
Geschäftsführer: Ronald Boers, Amtsgericht Hamburg HR B62 932
In your method, one way to better it would be to not have the pair as
the member of the function object split. What this does is evident in
the way you construct split via the for_each return. The pair of
vector would undergo copy construction that can be costly for a large
container.
What you could do is have a seperate pair<vector<int>,vector<int> >
and have split explicitly constructed using a reference to this pair
object that it would append the data to. Something like this:
pair<vector<int>,vector<int> > a;
for_each(p.begin(), p.end(), split(a));
and the split would be:
struct split : unary_function<void, pair<int,int> >
{
pair<vector<int>,vector<int> >& a;
split(pair<vector<int>,vector<int> >& a_) : a(a_){}
void operator()(pair<int,int> p)
{ a.first.push_back(p.first);
a.second.push_back(p.second); }
};
Also beneficial could be reserve on the two vector legs of the pair
with size of the original vector of the pairs.
On Mon, 16 Apr 2007, Richard Powell wrote:
> What would be the most effective way to convert vector<pair<int,int> >
> to pair<vector<int>,vector<int> >?
Depending on what you want to do with it afterwards, the most effective
way might be a proxy iterator. This means, however, that you don't end up
with a pair<vector<int>, vector<int>>, but instead just four iterators
that act like the begin() and end() iterators of these two (hypothetical)
vectors. Except that they're a different type.
Basically, you want to inject a boost::transform_iterator with a
boost/tr1::bind of std::pair<int,int>::first/second, respectively. The
resulting iterators iterate over the combined vector but present a view of
only the first/second value of each element.
If you actually want the vectors, there's no way around having three
vectors. However, your implementation below, because it returns by value,
actually has five vectors. You can optimize it by passing a pointer to an
externally provided vector to the split functor instead of having a local
one.
> I know I can do it as follows:
>
> struct split : unary_function<void, pair<int,int> >
> {
> pair<vector<int>,vector<int> > a;
> void operator()(pair<int,int> p) { a.first.push_back(p.first);
> a.second.push_back(p.second); }
> };
>
> ...
> vector<pair<int,int> > p;
> for (int i = 0; i < 100; i++)
> p.push_back(pair<int,int>(i,2*i));
>
> split s = for_each(p.begin(), p.end(), split());
> ...
>
Sebastian Redl
> What would be the most effective way to convert vector<pair<int,int> >
> to pair<vector<int>,vector<int> >?
If you just need to iterate over the pair<int,int>::first/second,
boost::transform_iterator might be the easiest. Follow this link to
see some code please
http://groups.google.co.uk/group/comp.lang.c++.moderated/msg/26b344960588d3a
c
This doesn't work, because split needs to be CopyConstructible. The
easiest fix is to make member a a pointer:
struct split : unary_function<void, pair<int,int> >
{
pair<vector<int>,vector<int> > * a;
split(pair<vector<int>,vector<int> >& a_) : a(&a_){}
void operator()(pair<int,int> p) {
a->first.push_back(p.first);
a->second.push_back(p.second);
}
};
Cheers,
Nicola Musatti
This is not guaranteed to work, because for_each is free to copy its
functor argument as many time as it wants. In a similar case I would
consider an explicit cycle to be the simpler solution.
> But I'm not very satisfied with that solution. It seems that I'll
> need to have 3 vectors at the end of the day, 1 of the original, and 2
> afterwards.
>
> Is there a better way?
Given that this is your original requirement I don't see how it may be
improved. What you may certainly do is not to copy your data from your
original vector but to refer to each elements' first and second
members when you traverse it.
Cheers,
Nicola Musatti
I think I should clarify my thoughts a little.
What I mean is not that I don't want 3 vectors, but instead I mean is
there some way that I can tell c++ that even though I have a
vector<pair<int, int> >, I want to treat it as a pair<vector<int>,
vector<int> > without very much overhead. Basically, I want a "cast"
that would do the work for me. But after some thought I realize this
is impossible because, as several have pointed out that the two are
fundamentally different data structures.
It does sound like you want a matrix data type. Maybe boost::ublas
can be of assistance. You could create your structure as
typedef boost::numeric::ublas::matrix<int> AudioChannels;
AudioChannels data(2, num_of_samples);
or similar.
uBLAS provides iterators that would allow you to iterate through the
structure in row-major or column-major order depending on what you
need. You can also create vector<int>s from the structure on a per-
column / per-row basis as needed, if and when you need to shift data
out of it.
Tom
As Maxim said transform_iterator seems to be the best solution.
Does a reference member make the containing class not CopyConstructible?
I tried the reference version at the Comeau Online, and it seems to
compile fine.
--
Seungbeom Kim
operator() should be const, btw.
> > This doesn't work, because split needs to be CopyConstructible. The
> > easiest fix is to make member a a pointer:
> >
> > struct split : unary_function<void, pair<int,int> >
> > {
> > pair<vector<int>,vector<int> > * a;
> > split(pair<vector<int>,vector<int> >& a_) : a(&a_){}
> > void operator()(pair<int,int> p) {
> > a->first.push_back(p.first);
> > a->second.push_back(p.second);
> > }
> > };
>
> Does a reference member make the containing class not CopyConstructible?
No, the class is CopyConstructible. Strictly speaking the standard
does not require CopyConstructible for functors in algorithms but
it's
wordings seem to imply CopyConstructible & Assignable, e.g. see
the note of 25/9:
"Unless otherwise specified, algorithms that take function objects
as arguments are permitted to copy those function objects freely[..]"
I interpret "copy freely" to allow both copy-construction as well as
assignment. But a class containing references has no feasible
compiler-generated copy assignment operator, see 12.8/12:
"A program is ill-formed if the class for which a
copy assignment operator is implicitly defined has:
[..]
- a non-static data member of reference type, or
[..]"
That is a good reason for using pointers instead of references
as members of functors.
Greetings from Bremen,
Daniel Krügler
--
You and Kim are correct. Thanks for your clarification.
Cheers,
Nicola Musatti
I would like to add that the ongoing conceptualized Standard
Library seems to restrict the requirements on callable entities
(aka "functors") used e.g. in std::for_each to be
MoveConstructible by means of requirement propagation
as explained in 14.9.1.1/2 of
http://www2.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2193.pdf
and the only explicit requirement on Function will be Callable1,
see
http://www2.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2084.pdf
These clearer requirements should allow the definition of
functors which contain references as members (instead of pointers).
There is a second part to that Note :
"[ Note: Unless otherwise specified, algorithms that take function
objects as arguments are permitted to copy those function
objects freely. Programmers for whom object identity is important
should consider using a wrapper class that points
to a noncopied implementation object, or some equivalent solution. -
end note ]"
What would that second part mean?
That Comeau accepts it - I think it interprets copy freely is to just
refer to copy and not assignment (or that there is no assignment
involved in this particular implementation). Is it defined as to what
copy freely would mean? Should one really not have any assignment
members in functors?
Also, even if there were copy involved - the compiler would shout
about it rather than it being UB. So, I would consider it safe.
Should one really not have any assignment
> members in functors?
>
Please read as : Should one really not have any reference members in
functors?
The second part is related to a situation described in
http://www2.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#92
and can be summarized to the following: Let's assume
you invoke std::remove_if with a functor and you have
the genious idea that you could simply call the invocations
of the functor's operator() call by incrementing a counter
each time to indirectly determine the position ("index")
of the currently checked element. This is not guaranteed
to work by simply adding the count state as normal
member to the functor, because that one could be copied.
Therefore it's recommended that you use an externally
stored state to realize this, where each functor references
this state, e.g. you have to modify the example as shown
below:
class Nth { // function object that returns true for the nth
element
private:
int nth; // element to return true for
int& count; // element counter
public:
Nth (int n, int& count) : nth(n), count(count) {
}
bool operator() (int) {
return ++count == nth;
}
};
> That Comeau accepts it - I think it interprets copy freely is to just
> refer to copy and not assignment (or that there is no assignment
> involved in this particular implementation).
I cannot follow your argumentation here. I did not say (in my first
answer) that an implementation *must* use assignment. So if
you use a functor with a reference member and this functor "works"
with some algorithm, this is does not proof that the standard did
allow assignments of functors.
> Is it defined as to what
> copy freely would mean? Should one really not have any assignment
> members in functors?
IMO, the original (that is currently existing in 14882:2003)
wording is not precise enougth to specify that. But - as I
said in my refining answer - the new C++ concepts (and
other newcomers as rvalue references) lead to lesser
requirements (and to a clearer languag!) on such functors
and it will be sufficient now, if these are MoveConstructible.
So neither CopyConstructible nor Assignable must be
provided by the functor.
But it can be advantagous, if a functor is both CopyConstructible
and Assignable, because both requirements are given by
normal function pointers. So, if you would like to be flexible
enough to use a functor where you would use a function
pointer, both requirements should be fulfilled.
Another example is e.g. std::set. If you use a non-assignable
comparison object here, you cannot copy-assign the set,
see 23.1.2/11:
"[..] When an associative container is copied, either
through a copy constructor or an assignment operator,
the target container shall then use the comparison
object from the container being copied, as if that
comparison object had been passed to the target
container in its constructor."
Of course if you would simply *move-assign* the
containers there would be no such problem.
> Also, even if there were copy involved - the compiler would shout
> about it rather than it being UB. So, I would consider it safe.
Yes, in this sense it's a safe thing. But it can cause a lot
of grief for a company with a large code base that wants
to update it's standard library. In this case earlier working
code *could* loudly resist to compile now - with possibly
weeks of adaption work.
Greetings from Bremen,
Daniel Krügler
--
Thanks for the explanation, Daniel and the insight on std::set. In
fact, I actually faced the problem owing to wierd problem that came
across me sometime ago. I used 3 techniques:
http://learningcppisfun.blogspot.com/2007/02/functors-with-state-4-alternative.html
The fourth was suggestion that I came across and used a reference
member very nicely in the predicate to keep the state. I guess, that
suffers from this problem then.
> But it can be advantagous, if a functor is both CopyConstructible
> and Assignable, because both requirements are given by
> normal function pointers. So, if you would like to be flexible
> enough to use a functor where you would use a function
> pointer, both requirements should be fulfilled.
I wonder how that can be advantageous? The problem comes when the
functor has state that has to be maintained while copy/assign -
function pointers cannot have state unless they use a global/static
variable or a reference/pointer to an external object. That shouldn't
be the problem with functors as well. Otherwise, we can use functors
in place of plain functions without needing to have to worry about
that. Since keeping a pointer instead of a reference solves the issue,
I guess that fine enough for now.
Regards.
I will be upfront with you: Several of the tested techniques
have severe problems in the code:
1) You should additionally add #include <ostream> in all
examples, otherwise it's not guaranteed that the needed
operator<<(basic_ostream<char,traits>&, const char*)
is available via #include <iostream>. You also need
<stddef.h> because you use size_t in PrintVector.
2) The syntax used in trial #1 to define the static member
is invalid. Most probably you want to use this one:
template<typename T>
int IsEvenIndex<T>::index = 0;
3) The second output presented in trial #2 makes no
sense compared to the first and is probably wrong,
because the contents of myintVector and myotherintVector
are not influenced by the changes (assuming the same
standard library). The expected output for this special
library is probably something like this:
Printing vector contents
10 20 30 40 50 60 70 80 90 100
Printing vector contents
30 50 70 90
Printing vector contents
10 20 40 60 80 100
Printing vector contents
50 60 70 80 90 100
4) The insertion used in trial 2 is needlessly complicated
and could be replaced by the simple assignment
myanotherintVector.assign(itend, myintVector.end());
6) Some conclusions are basically wrong, e.g. this one
from #2: "Now, how would this predicate be passed? By
reference or by value? This is unspecified by the standards."
The standard says that the predicates *are passed* by value.
7) Further on the examples would be more readable, if you
had used a simpler initialization technique, e.g. a single
loop like this:
for (int i = 1; i <= 10; ++i) {
myintVector.push_back(10 * i);
}
The individual push_back's use a lot of space and more
severe: I had to check each single push_back to check,
whether the series of elements follow a special rule or not.
This rule is directly implied in the loop above.
8) The easy fix of #2 is to use an external state, that is
replacing the index int member in IsEvenIndex by int& index
and adding a second c'tor argument. Note that this externally
stored index has a similar role as the external state of the
referenced refVec.
> > But it can be advantagous, if a functor is both CopyConstructible
> > and Assignable, because both requirements are given by
> > normal function pointers. So, if you would like to be flexible
> > enough to use a functor where you would use a function
> > pointer, both requirements should be fulfilled.
>
> I wonder how that can be advantageous? The problem comes when the
> functor has state that has to be maintained while copy/assign -
> function pointers cannot have state unless they use a global/static
> variable or a reference/pointer to an external object.
I was discussing advantages in general, not for this special
example which needs state. When you need state, a functor
is often the right choice, but you could also use tr1::bind
with a function pointer (with an additional argument accepting
the state), and transferring the state via the tr1:bind argument.
Greetings from Bremen,
Daniel Krügler
--
Sorry, if my blog post was not clear on this, but the output I have
shown is what you would get with the version of the functor with the
static member (not the mutable one). And it is as expected. What you
have posted above is the output that you would get with the non-static
state variable.
No worries, thank you for your valuable inputs. :)
>
> 1) You should additionally add #include <ostream> in all
> examples, otherwise it's not guaranteed that the needed
> operator<<(basic_ostream<char,traits>&, const char*)
> is available via #include <iostream>. You also need
> <stddef.h> because you use size_t in PrintVector.
>
About size_t -> I should have had qualified it with the std::
namespace. Otherwise, I think I need not explicitly include <cstddef>
as std::vector and std::allocator have size_type typedef-ed on it and
I would expect that size_t is available with <vector>. <vector> should
include all the dependent headers and explicitly adding its
dependencies should not be needed for people who use it. In any case,
std::vector<T>::size_type is what I should have had put it as.
About operator<< with ostream for const char* -> I guess since
<iostream> has cout etc declared it should also contain the operator<<
overloads that would be needed for it to work with atleast the
fundamental types. Any new type introduced, for example, std::string
should have the overload provided in its own respective headers that
defines it. If std::cout << int works, I would expect std::cout <<
const char* works. Is it not the case?
>
> 2) The syntax used in trial #1 to define the static member
> is invalid. Most probably you want to use this one:
>
> template<typename T>
> int IsEvenIndex<T>::index = 0;
>
Right. Since I provided the definition just for the int
specialization, I should have had atleast put it with an empty
template tag:
template<>
int IsEvenIndex<int>::index = 0;
But what you suggest is a generic one that should take care of the
definition for all template instantiations. That's an error on my
part.
>
> 4) The insertion used in trial 2 is needlessly complicated
> and could be replaced by the simple assignment
> myanotherintVector.assign(itend, myintVector.end());
>
Yes, assign would work as well. But I don't necessarily consider
insert as complicated because it takes an extra argument. It's just
there are 2 ways and there may be more and that its just a matter of
choice.
>
> 6) Some conclusions are basically wrong, e.g. this one
> from #2: "Now, how would this predicate be passed? By
> reference or by value? This is unspecified by the standards."
>
> The standard says that the predicates *are passed* by value.
>
I guessed, that implementations were allowed to copy them freely but
not that they could not accept the arguments by reference. If that is
not the case, please feel to correct me.
>
> 7) Further on the examples would be more readable, if you
> had used a simpler initialization technique, e.g. a single
> loop like this:
>
> for (int i = 1; i <= 10; ++i) {
> myintVector.push_back(10 * i);
>
> }
>
> The individual push_back's use a lot of space and more
> severe: I had to check each single push_back to check,
> whether the series of elements follow a special rule or not.
> This rule is directly implied in the loop above.
>
Yeah, I understand. :) I replaced those.
>
> 8) The easy fix of #2 is to use an external state, that is
> replacing the index int member in IsEvenIndex by int& index
> and adding a second c'tor argument. Note that this externally
> stored index has a similar role as the external state of the
> referenced refVec.
>
Now, aren't you going against your own correction? Storing a reference
member with a functor?
>
> > > But it can be advantagous, if a functor is both CopyConstructible
> > > and Assignable, because both requirements are given by
> > > normal function pointers. So, if you would like to be flexible
> > > enough to use a functor where you would use a function
> > > pointer, both requirements should be fulfilled.
>
> > I wonder how that can be advantageous? The problem comes when the
> > functor has state that has to be maintained while copy/assign -
> > function pointers cannot have state unless they use a global/static
> > variable or a reference/pointer to an external object.
>
> I was discussing advantages in general, not for this special
> example which needs state. When you need state, a functor
> is often the right choice, but you could also use tr1::bind
> with a function pointer (with an additional argument accepting
> the state), and transferring the state via the tr1:bind argument.
>
Yeah, but when you used bind, it doesn't remain a function pointer
anymore. Does it?
The last sentence is correct, the previous ones not. The standard
says in the table for "Container requirements" (23.1) that
vector<>::size_type is an unsigned integral type that can
represent any non-negative value of difference_type, there is no
direct dependency on size_t (which itself is an
implementation-defined unsigned integral type). Only bitset and
the upcoming array, tuples, and unordered containers do have
an implicit dependency on (std::)size_t.
> About operator<< with ostream for const char* -> I guess since
> <iostream> has cout etc declared it should also contain the operator<<
> overloads that would be needed for it to work with atleast the
> fundamental types. Any new type introduced, for example, std::string
> should have the overload provided in its own respective headers that
> defines it. If std::cout << int works, I would expect std::cout <<
> const char* works. Is it not the case?
This is (currently) not the case. According to 27.3 <iostream>
provides the eight iostream objects, there is no requirement that
it also has to bring the free extractors and insertors into scope
(Note, that in contrast to the insertion of double, int, etc, the
const char* insertion is a non-member operator).
There are currently considerations to demand that <iostream>
includes <ostream> and <istream>, but not in the currently
valid standard.
> > 2) The syntax used in trial #1 to define the static member
> > is invalid. Most probably you want to use this one:
> >
> > template<typename T>
> > int IsEvenIndex<T>::index = 0;
> >
>
> Right. Since I provided the definition just for the int
> specialization, I should have had atleast put it with an empty
> template tag:
>
> template<>
> int IsEvenIndex<int>::index = 0;
Yes.
> > 6) Some conclusions are basically wrong, e.g. this one
> > from #2: "Now, how would this predicate be passed? By
> > reference or by value? This is unspecified by the standards."
> >
> > The standard says that the predicates *are passed* by value.
> >
>
> I guessed, that implementations were allowed to copy them freely but
> not that they could not accept the arguments by reference. If that is
> not the case, please feel to correct me.
OK, this was a misunderstanding on my side. I interpreted your
sentence to be applied on the standard algorithm signatures.
You are right, that there exists no requirement, that internally
helper functions of the STL need to copy the functors, they
could also be transferred via a const reference.
> > 8) The easy fix of #2 is to use an external state, that is
> > replacing the index int member in IsEvenIndex by int& index
> > and adding a second c'tor argument. Note that this externally
> > stored index has a similar role as the external state of the
> > referenced refVec.
> >
>
> Now, aren't you going against your own correction? Storing a reference
> member with a functor?
As explained in my other postings, the decision on using either
a pointer or reference *internally* depends on the use-cases.
For a greater application area Assignable is probably advantagous
compared to MoveConstructible, so yes, you should use an
int* as member instead of my proposed int& (but I would use
an int& as c'tor argument to make clear that this must be a
non-nullable argument).
> > I was discussing advantages in general, not for this special
> > example which needs state. When you need state, a functor
> > is often the right choice, but you could also use tr1::bind
> > with a function pointer (with an additional argument accepting
> > the state), and transferring the state via the tr1:bind argument.
> >
>
> Yeah, but when you used bind, it doesn't remain a function pointer
> anymore. Does it?
Right, not for the overall functor. But this does not make
functions a second class citizen here, because for similar
reasons you often have to use bind to adapt non-function
functor signatures to otherwise required signatures.
Greetings from Bremen,
Daniel Krügler
--