Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Simple generalised reverse problem.

35 views
Skip to first unread message

Paul

unread,
Dec 29, 2015, 9:17:02 AM12/29/15
to
I am writing code to swap elements of vectors of general type and reverse vectors. The following code (see below asterisks) has been tested and seems to work (so far).

But clearly, this is reinventing the wheel. My reverse function swaps so surely it should implement the swap function. However, I can't write it that way without getting a compile error. If I replace the body of the for loop
by swap<T>(vec[i], vec[j]); then I get a compile error (which follows an attempted function call) that the swap function can't be matched. I'd be grateful if someone could explain why swap<T>(vec[i], vec[j]); is ambiguous and what I should do about it.

Many thanks for your help.

Paul


***************************************************
template<typename T>
void swap(T& x, T&y)
{
T tmp = x;
x = y;
y = tmp;
}

template<typename T>
void reverse(vector<T>& vec)
{
if(vec.empty())
return;

for(int i = 0, j = vec.size() - 1; i < j; ++i, --j)
{
T tmp = vec[i];
vec[i] = vec[j];
vec[j] = tmp;
}
}

Paavo Helde

unread,
Dec 29, 2015, 10:00:11 AM12/29/15
to
Paul <peps...@gmail.com> wrote in
news:29f84008-e901-4599...@googlegroups.com:

> I am writing code to swap elements of vectors of general type and
> reverse vectors. The following code (see below asterisks) has been
> tested and seems to work (so far).
>
> But clearly, this is reinventing the wheel. My reverse function swaps
> so surely it should implement the swap function. However, I can't
> write it that way without getting a compile error. If I replace the
> body of the for loop by swap<T>(vec[i], vec[j]); then I get a
> compile error (which follows an attempted function call) that the swap
> function can't be matched. I'd be grateful if someone could explain
> why swap<T>(vec[i], vec[j]); is ambiguous and what I should do about
> it.

The code might conflict with std::swap(). If you want better help, post a
complete failing code example and error messages.

hth
Paavo

Paul

unread,
Dec 29, 2015, 10:17:39 AM12/29/15
to
Ok, complete code and error messages are below. I have renamed swap to remove that concern. Many thanks.

Paul

#include <iostream>
#include <stdexcept>
#include <vector>
using std::vector;

template<typename T>
void swap1(T& x, T&y)
{
T tmp = x;
x = y;
y = tmp;
}

template<typename T>
void reverse(vector<T>& vec)
{
if(vec.empty())
return;

for(int i = 0, j = vec.size() - 1; i < j; ++i, --j)
swap1<T>(vec[i], vec[j]);
}

int main()
{
vector<bool> vec = {true, false, false};
reverse<bool>(vec);
for(int i = 0; i < vec.size(); ++i)
std::cout << std::endl << vec[i];

}

Errors are:

||=== Build: Debug in reverse (compiler: GNU GCC Compiler) ===|
C:\Users\silviadaniel\Desktop\reverse\main.cpp||In function 'int main()':|
C:\Users\silviadaniel\Desktop\reverse\main.cpp|28|warning: comparison between signed and unsigned integer expressions [-Wsign-compare]|
C:\Users\silviadaniel\Desktop\reverse\main.cpp||In instantiation of 'void reverse(std::vector<T>&) [with T = bool]':|
C:\Users\silviadaniel\Desktop\reverse\main.cpp|27|required from here|
C:\Users\silviadaniel\Desktop\reverse\main.cpp|21|error: no matching function for call to 'swap1(std::vector<bool>::reference, std::vector<bool>::reference)'|
C:\Users\silviadaniel\Desktop\reverse\main.cpp|21|note: candidate is:|
C:\Users\silviadaniel\Desktop\reverse\main.cpp|7|note: template<class T> void swap1(T&, T&)|
C:\Users\silviadaniel\Desktop\reverse\main.cpp|7|note: template argument deduction/substitution failed:|
C:\Users\silviadaniel\Desktop\reverse\main.cpp|21|note: cannot convert '(& vec)->std::vector<bool, _Alloc>::operator[]<std::allocator<bool> >(((std::vector<bool>::size_type)i))' (type 'std::vector<bool>::reference {aka std::_Bit_reference}') to type 'bool&'|
||=== Build failed: 1 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|

Alf P. Steinbach

unread,
Dec 29, 2015, 10:47:42 AM12/29/15
to
On 12/29/2015 4:17 PM, Paul wrote:
>
> int main()
> {
> vector<bool> vec = {true, false, false};

vector<bool> is specialized to allow the bools to be represented with
one bit each.

Consequently you do not get real references to `bool` items, but instead
proxy objects that act somewhat like references:

(constructor)
constructs the reference. Accessible only to std::vector<bool> itself
(public member function)
(destructor)
destroys the reference
(public member function)
operator=
assigns a bool to the referenced bit
(public member function)
operator bool
returns the referenced bit
(public member function)
flip
flips the referenced bit
(public member function)

From <url:
http://en.cppreference.com/w/cpp/container/vector_bool/reference>
(except that term "lvalue" there is misplaced, maybe very informal, or
else just wrong).

One alternative, when you want that, is a `dequeue<bool>`. In the other
direction, you could generalize the swap function with an overload that
handles this case.


> reverse<bool>(vec);
> for(int i = 0; i < vec.size(); ++i)
> std::cout << std::endl << vec[i];
>
> }

Cheers & hth.,

- Alf

Cholo Lennon

unread,
Dec 29, 2015, 10:53:55 AM12/29/15
to
std::vector<bool> is not the best option to test your algorithm. Check this:

http://stackoverflow.com/questions/17794569/why-is-vectorbool-not-a-stl-container



Regards


--
Cholo Lennon
Bs.As.
ARG

Alf P. Steinbach

unread,
Dec 29, 2015, 10:59:13 AM12/29/15
to
On 12/29/2015 4:47 PM, Alf P. Steinbach wrote:
>
> One alternative, when you want that, is a `dequeue<bool>`. In the other
> direction, you could generalize the swap function with an overload that
> handles this case.

OK, I checked how `std::reverse` does it, and it uses `std::iter_swap`
instead of using `std::swap` directly.

Daniel

unread,
Dec 29, 2015, 11:10:54 AM12/29/15
to
On Tuesday, December 29, 2015 at 10:47:42 AM UTC-5, Alf P. Steinbach wrote:
> On 12/29/2015 4:17 PM, Paul wrote:
> >
> > int main()
> > {
> > vector<bool> vec = {true, false, false};
>
> vector<bool> is specialized to allow the bools to be represented with
> one bit each.
>
> Consequently you do not get real references to `bool` items, but instead
> proxy objects that act somewhat like references:
>

This seems to work (with VS 2015):

template<typename T>
void reverse(vector<T>& vec)
{
if (vec.empty())
return;

using std::swap;

for (int i = 0, j = vec.size() - 1; i < j; ++i, --j)
swap(vec[i], vec[j]);
}

int main()
{
vector<bool> vec = { true, false, false };
reverse<bool>(vec);
for (int i = 0; i < vec.size(); ++i)
std::cout << std::endl << vec[i];
}

Output:

0
0
1

Paul

unread,
Dec 29, 2015, 11:34:03 AM12/29/15
to
Yes, using std::swap works (on any compiler). I was trying to write the code myself, rather than using library functions.

Paul

peps...@gmail.com

unread,
Dec 29, 2015, 11:40:16 AM12/29/15
to
Sorry, I take that back. std::swap doesn't work on my compiler in the above example -- gcc. Interesting that VS 2015 accepts my example.

Paul

Alf P. Steinbach

unread,
Dec 29, 2015, 11:47:54 AM12/29/15
to
On 12/29/2015 5:33 PM, Paul wrote:
>
> Yes, using std::swap works (on any compiler). I was trying to write
> the code myself, rather than using library functions.

I failed to find that specialization over at cppreference.com, but
finally found it in C++11 §23.3.7/5:

static void swap(reference x, reference y) noexcept;

So, it's not just a compiler-specific extension.

Paavo Helde

unread,
Dec 29, 2015, 11:54:05 AM12/29/15
to
Paul <peps...@gmail.com> wrote in
news:b4605ec5-4d60-4bfd...@googlegroups.com:
std::vector<bool> is a more or less failed experiment by the C++ standard
committee; for supporting it you need to provide special specialization
or overload of your swap1() (assuming you don't want to just use
std::swap() by whatever reasons):

#include <iostream>
#include <stdexcept>
#include <vector>
using std::vector;

template<typename T>
void swap1(T& x, T&y) {
T tmp = x;
x = y;
y = tmp;
}

void swap1(vector<bool>::reference x, vector<bool>::reference y) {
bool tmp = x;
x = y;
y = tmp;
}

template<typename T>
void reverse(vector<T>& vec) {
if (vec.empty())
return;

for (int i = 0, j = vec.size() - 1; i < j; ++i, --j)
swap1(vec[i], vec[j]);
}

int main() {
vector<bool> vec = {true, false, false};
reverse<bool>(vec);
for (int i = 0; i < vec.size(); ++i)

Marcel Mueller

unread,
Dec 29, 2015, 2:01:05 PM12/29/15
to
On 29.12.15 15.16, Paul wrote:
> But clearly, this is reinventing the wheel. My reverse function swaps so surely it should implement the swap function. However, I can't write it that way without getting a compile error. If I replace the body of the for loop
> by swap<T>(vec[i], vec[j]); then I get a compile error (which follows an attempted function call) that the swap function can't be matched. I'd be grateful if someone could explain why swap<T>(vec[i], vec[j]); is ambiguous and what I should do about it.
>
> Many thanks for your help.


> template<typename T>
> void swap(T& x, T&y)
> {
> T tmp = x;
> x = y;
> y = tmp;
> }

Do not redefine the standard function swap. This is probably your problem.


Marcel

Mr Flibble

unread,
Dec 29, 2015, 2:12:44 PM12/29/15
to
Unless this function template is in the std namespace he is not
redefining the standard function swap. Overloading swap is sometimes
useful sausages.

/Flibble

Marcel Mueller

unread,
Dec 29, 2015, 4:22:03 PM12/29/15
to
On 29.12.15 20.13, Mr Flibble wrote:
>> Do not redefine the standard function swap. This is probably your
>> problem.
>
> Unless this function template is in the std namespace he is not
> redefining the standard function swap.

bad code style anyway.

> Overloading swap is sometimes
> useful sausages.

Yes, but only as partial specialization for custom types.


Marcel

Mr Flibble

unread,
Dec 29, 2015, 4:46:51 PM12/29/15
to
On 29/12/2015 21:21, Marcel Mueller wrote:
> On 29.12.15 20.13, Mr Flibble wrote:
>>> Do not redefine the standard function swap. This is probably your
>>> problem.
>>
>> Unless this function template is in the std namespace he is not
>> redefining the standard function swap.
>
> bad code style anyway.

Only because he is not specializing it for custom types sausages.

/Flibble
0 new messages