473,327 Members | 2,012 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,327 software developers and data experts.

algorith implementation

template <class OutputIterator, class Size, class T>
void fill_n (OutputIterator first, Size n, const T& value)
{
while (n-- 0) *first++ = value;
}

If Size must be convertible to an integral type is this not an
implementation that excludes passing an enum value as the second
parameter? An enum value is convertible to an integral type so the
implementation does not match the specification.

Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------
http://www.usenet.com
Aug 20 '06 #1
26 1433
Fraser Ross wrote:
template <class OutputIterator, class Size, class T>
void fill_n (OutputIterator first, Size n, const T& value)
{
while (n-- 0) *first++ = value;
}

If Size must be convertible to an integral type is this not an
implementation that excludes passing an enum value as the second
parameter? An enum value is convertible to an integral type so the
implementation does not match the specification.
Correct. Where did you find this one? A better way would be to make
it

void fill_n (OutputIterator first, Size n_arg, const T& value)
{
size_t n = n_arg; ...

, probably.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 20 '06 #2
Victor Bazarov wrote:
Correct. Where did you find this one?
I found the same issue in gcc's STL. Indeed sgi's STL documentation
defines the requirement to be that Size must be an integral type.

Jens
Aug 20 '06 #3
Jens Theisen wrote:
Victor Bazarov wrote:
>Correct. Where did you find this one?

I found the same issue in gcc's STL. Indeed sgi's STL documentation
defines the requirement to be that Size must be an integral type.
The requirement now exists in the Standard (since 1997), so any C++
standard library implementation that doesn't use a local variable is
not going to work with enums, as the OP hinted.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 20 '06 #4
I'm using the Rogue Wave STL with BCB6.

Fraser.

Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------
http://www.usenet.com
Aug 20 '06 #5
Jens Theisen wrote:
Victor Bazarov wrote:
>Correct. Where did you find this one?

I found the same issue in gcc's STL. Indeed sgi's STL documentation
defines the requirement to be that Size must be an integral type.
But the standard does say otherwise:

[25.2.5]

template<class ForwardIterator, class T>
void fill(ForwardIterator first, ForwardIterator last, const T& value);

template<class OutputIterator, class Size, class T>
void fill_n(OutputIterator first, Size n, const T& value);

Requires: Type T is Assignable (23.1), Size is convertible to an integral
type (4.7, 12.3).

Effects: Assigns value through all the iterators in the range [first,
last)or [first, first +n).

Best

Kai-Uwe Bux

Aug 20 '06 #6
Victor Bazarov wrote:
The requirement now exists in the Standard (since 1997), so any C++
standard library implementation that doesn't use a local variable is
not going to work with enums, as the OP hinted.
The standard I'm looking at was released 1998. And after all, it's
C++98, isn't it? How come that I still have the "convertible" variant?

Jens
Aug 20 '06 #7

"Victor Bazarov" <v.********@comAcast.netskrev i meddelandet
news:yq******************************@comcast.com. ..
Fraser Ross wrote:
> template <class OutputIterator, class Size, class T>
void fill_n (OutputIterator first, Size n, const T& value)
{
while (n-- 0) *first++ = value;
}

If Size must be convertible to an integral type is this not an
implementation that excludes passing an enum value as the second
parameter? An enum value is convertible to an integral type so the
implementation does not match the specification.

Correct. Where did you find this one? A better way would be to
make
it

void fill_n (OutputIterator first, Size n_arg, const T& value)
{
size_t n = n_arg; ...

, probably.
That would fail for negative values instead.

This is tricky. :-)
Bo Persson
Aug 20 '06 #8
Bo Persson wrote:
"Victor Bazarov" <v.********@comAcast.netskrev i meddelandet
news:yq******************************@comcast.com. ..
>Fraser Ross wrote:
>> template <class OutputIterator, class Size, class T>
void fill_n (OutputIterator first, Size n, const T& value)
{
while (n-- 0) *first++ = value;
}

If Size must be convertible to an integral type is this not an
implementation that excludes passing an enum value as the second
parameter? An enum value is convertible to an integral type so the
implementation does not match the specification.
Correct. Where did you find this one? A better way would be to
make
it

void fill_n (OutputIterator first, Size n_arg, const T& value)
{
size_t n = n_arg; ...

, probably.

That would fail for negative values instead.
Is that really a problem? Is the behavior of std::fill_n even defined by
the standard when n_arg is negative?

--
Clark S. Cox III
cl*******@gmail.com
Aug 20 '06 #9

"Clark S. Cox III" <cl*******@gmail.comskrev i meddelandet
news:12*************@corp.supernews.com...
Bo Persson wrote:
>"Victor Bazarov" <v.********@comAcast.netskrev i meddelandet
news:yq******************************@comcast.com ...
>>Fraser Ross wrote:
template <class OutputIterator, class Size, class T>
void fill_n (OutputIterator first, Size n, const T& value)
{
while (n-- 0) *first++ = value;
}

If Size must be convertible to an integral type is this not an
implementation that excludes passing an enum value as the second
parameter? An enum value is convertible to an integral type so
the
implementation does not match the specification.
Correct. Where did you find this one? A better way would be to
make
it

void fill_n (OutputIterator first, Size n_arg, const T& value)
{
size_t n = n_arg; ...

, probably.

That would fail for negative values instead.

Is that really a problem? Is the behavior of std::fill_n even
defined by
the standard when n_arg is negative?
Yes, it is. The committee has specifically rejected undefined
behaviour for that case.

http://www.open-std.org/jtc1/sc22/wg...n2025.html#426
Bo Persson
Aug 20 '06 #10
Jens Theisen wrote:
Victor Bazarov wrote:
>The requirement now exists in the Standard (since 1997), so any C++
standard library implementation that doesn't use a local variable is
not going to work with enums, as the OP hinted.

The standard I'm looking at was released 1998. And after all, it's
C++98, isn't it? How come that I still have the "convertible" variant?
I must have misunderstood. The Standard says "convertible". However,
the implementation that makes direct use of the argument and tries to
decrement it using -- is not going to work with a "convertible" type.
It will only work with true integral type.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 21 '06 #11
A suitable implementation is easy enough to make. It surprises me how
much library code uses pre increment and decrement operators. They can
be less efficient.

Fraser.

void fill_n (OutputIterator first, Size n_arg, const T& value)
{
size_t n = n_arg; ...

, probably.

That would fail for negative values instead.

This is tricky. :-)
Bo Persson


Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------
http://www.usenet.com
Aug 21 '06 #12
I meant to type post not pre.
"Fraser Ross"
It surprises me how
much library code uses pre increment and decrement operators. They
can
be less efficient.


Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------
http://www.usenet.com
Aug 21 '06 #13
Fraser Ross wrote:
A suitable implementation is easy enough to make.

Please don't top-post. Your replies belong following or interspersed
with properly trimmed quotes. See the majority of other posts in the
newsgroup, or the group FAQ list:
<http://www.parashift.com/c++-faq-lite/how-to-post.html>


Brian
Aug 21 '06 #14

"Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet
news:11***********@sp6iad.superfeed.net...
>A suitable implementation is easy enough to make. It surprises me
how
much library code uses pre increment and decrement operators. They
can
be less efficient.

Fraser.

I don't think it is obvious how to select a proper integral type for
n, when you don't know what type Size might be. In this case, if n_arg
happens to be negative, converting it to size_t will not work well.

If Size happens to be a class type with a user defined convertion
operator, how do we know what type(s) it will convert to? Signed, or
unsigned?
Bo Persson

>
void fill_n (OutputIterator first, Size n_arg, const T& value)
{
size_t n = n_arg; ...

, probably.

That would fail for negative values instead.

This is tricky. :-)
Bo Persson

Aug 21 '06 #15
Bo Persson posted:

I don't think it is obvious how to select a proper integral type for
n, when you don't know what type Size might be. In this case, if n_arg
happens to be negative, converting it to size_t will not work well.

Perhaps something like this:

(It doesn't compile but you get the idea)

enum MyEnum { a,b,c,d,e,f };

template<class T, bool is_signed = ((T)-1 < 0)>
void Func(T arg);

template<class T>
void Func<T,true>(T arg)
{
long i = arg;
}

template<class T>
void Func<T,false>(T arg)
{
long unsigned i = arg;
}

int main()
{
MyEnum obj;

Func(obj);
}

--

Frederick Gotham
Aug 21 '06 #16
Bo Persson wrote:
>
"Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet
news:11***********@sp6iad.superfeed.net...
>>A suitable implementation is easy enough to make. It surprises me
how
much library code uses pre increment and decrement operators. They
can
be less efficient.

Fraser.


I don't think it is obvious how to select a proper integral type for
n, when you don't know what type Size might be. In this case, if n_arg
happens to be negative, converting it to size_t will not work well.

If Size happens to be a class type with a user defined convertion
operator, how do we know what type(s) it will convert to? Signed, or
unsigned?
Who says that it is necessary to make a guess as to whether Size converts to
signed or unsigned? What about:

template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
for ( std::size_t i = 0; i < n; ++i ) {
*first = value;
++first;
}
}

One could use specialization tricks to save the local variable when Size is
an arithmetic type.
> void fill_n (OutputIterator first, Size n_arg, const T& value)
{
size_t n = n_arg; ...

, probably.
That would fail for negative values instead.

This is tricky. :-)
Best

Kai-Uwe Bux
Aug 21 '06 #17

"Frederick Gotham" <fg*******@SPAM.comskrev i meddelandet
news:1J*******************@news.indigo.ie...
Bo Persson posted:

>I don't think it is obvious how to select a proper integral type
for
n, when you don't know what type Size might be. In this case, if
n_arg
happens to be negative, converting it to size_t will not work well.


Perhaps something like this:

(It doesn't compile but you get the idea)
Yes, it solves some of the problems, but not all.

How do we separate

enum E1 { a = -42 };

from

enum E2 { a = UINT_MAX};

??

Or, even worse

struct T1
{
operator int();
};

from

struct T2
{
operator unsigned long();
};

??

I don't know? Perhaps this really is a defect in the standard?
>
enum MyEnum { a,b,c,d,e,f };

template<class T, bool is_signed = ((T)-1 < 0)>
void Func(T arg);
This will not work for the structs, that are convertible *to* an
integral type, but not *from*.
Bo Persson
>
template<class T>
void Func<T,true>(T arg)
{
long i = arg;
}

template<class T>
void Func<T,false>(T arg)
{
long unsigned i = arg;
}

int main()
{
MyEnum obj;

Func(obj);
}

--

Frederick Gotham

Aug 21 '06 #18

"Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet
news:ec**********@murdoch.acc.Virginia.EDU...
Bo Persson wrote:
>>
"Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet
news:11***********@sp6iad.superfeed.net...
>>>A suitable implementation is easy enough to make. It surprises me
how
much library code uses pre increment and decrement operators.
They
can
be less efficient.

Fraser.


I don't think it is obvious how to select a proper integral type
for
n, when you don't know what type Size might be. In this case, if
n_arg
happens to be negative, converting it to size_t will not work well.

If Size happens to be a class type with a user defined convertion
operator, how do we know what type(s) it will convert to? Signed,
or
unsigned?

Who says that it is necessary to make a guess as to whether Size
converts to
signed or unsigned? What about:

template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
for ( std::size_t i = 0; i < n; ++i ) {
*first = value;
++first;
}
}
Yes, we are getting closer. :-)

My compiler would complain about a signed/unsigned comparison when
Size really is signed.
One could use specialization tricks to save the local variable when
Size is
an arithmetic type.
Perhaps we could have an overload

template < typename OutIter, typename T >
void fill_n ( OutIter first, std::size_t n, const T & value );

to catch the cases where std::size_t is the proper type?

That would leave the signed case for the original version. Wouldn't
that work?
Bo Persson
Aug 21 '06 #19
Bo Persson wrote:
>
"Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet
news:ec**********@murdoch.acc.Virginia.EDU...
>Bo Persson wrote:
>>>
"Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet
news:11***********@sp6iad.superfeed.net...
A suitable implementation is easy enough to make. It surprises me
how
much library code uses pre increment and decrement operators.
They
can
be less efficient.

Fraser.
I don't think it is obvious how to select a proper integral type
for
n, when you don't know what type Size might be. In this case, if
n_arg
happens to be negative, converting it to size_t will not work well.

If Size happens to be a class type with a user defined convertion
operator, how do we know what type(s) it will convert to? Signed,
or
unsigned?

Who says that it is necessary to make a guess as to whether Size
converts to
signed or unsigned? What about:

template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
for ( std::size_t i = 0; i < n; ++i ) {
*first = value;
++first;
}
}

Yes, we are getting closer. :-)

My compiler would complain about a signed/unsigned comparison when
Size really is signed.
It should not. Such comparison is handled gracefully by promotion rules. I
think, the code is required to compile.

>One could use specialization tricks to save the local variable when
Size is an arithmetic type.

Perhaps we could have an overload

template < typename OutIter, typename T >
void fill_n ( OutIter first, std::size_t n, const T & value );

to catch the cases where std::size_t is the proper type?

That would leave the signed case for the original version. Wouldn't
that work?
I would add overloads for all integral types.
Best

Kai-Uwe Bux

Aug 21 '06 #20

"Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet
news:ec**********@murdoch.acc.Virginia.EDU...
Bo Persson wrote:
>>
"Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet
news:ec**********@murdoch.acc.Virginia.EDU...
>>Bo Persson wrote:
"Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet
news:11***********@sp6iad.superfeed.net...
>A suitable implementation is easy enough to make. It surprises
>me
>how
much library code uses pre increment and decrement operators.
They
can
be less efficient.
>
Fraser.
I don't think it is obvious how to select a proper integral type
for
n, when you don't know what type Size might be. In this case, if
n_arg
happens to be negative, converting it to size_t will not work
well.

If Size happens to be a class type with a user defined convertion
operator, how do we know what type(s) it will convert to? Signed,
or
unsigned?

Who says that it is necessary to make a guess as to whether Size
converts to
signed or unsigned? What about:

template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
for ( std::size_t i = 0; i < n; ++i ) {
*first = value;
++first;
}
}

Yes, we are getting closer. :-)

My compiler would complain about a signed/unsigned comparison when
Size really is signed.

It should not. Such comparison is handled gracefully by promotion
rules. I
think, the code is required to compile.
It does with a warning, but the result is incorrect. :-(

If Size is ptrdiff_t for example, and n is negative, comparing to a
size_t doesn't work.

We are on the right track though, and I think this one could work:

template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
if (0 < n) // n must be positive
{
for ( std::size_t count = n; 0 < count; --count ) {
*first = value;
++first;
}
}
}

If we sort out the possibly negative n first, the remaining values
must be convertible to size_t (assuming size_t is the largest unsigned
type :-).
Bo Persson
Aug 22 '06 #21
Bo Persson posted:
My compiler would complain about a signed/unsigned comparison when
Size really is signed.

Simply cast one of them -- I regularly use casts to suppress compiler
warnings, e.g.:

for(size_t i = MAX - 1; i != (size_t)-1; --i)

--

Frederick Gotham
Aug 22 '06 #22

"Frederick Gotham" <fg*******@SPAM.comskrev i meddelandet
news:Ce*******************@news.indigo.ie...
Bo Persson posted:
>My compiler would complain about a signed/unsigned comparison when
Size really is signed.


Simply cast one of them -- I regularly use casts to suppress
compiler
warnings, e.g.:

for(size_t i = MAX - 1; i != (size_t)-1; --i)
That just works sometimes.

If the signed value really is negative, it doesn't help.

int x = -5;
unsigned y = UINT_MAX;

if (x < y)
...
Bo Persson
Aug 22 '06 #23
Bo Persson wrote:
"Frederick Gotham" <fg*******@SPAM.comskrev i meddelandet
news:Ce*******************@news.indigo.ie...
>Bo Persson posted:
>>My compiler would complain about a signed/unsigned comparison when
Size really is signed.


Simply cast one of them -- I regularly use casts to suppress
compiler
warnings, e.g.:

for(size_t i = MAX - 1; i != (size_t)-1; --i)

That just works sometimes.

If the signed value really is negative, it doesn't help.

int x = -5;
unsigned y = UINT_MAX;

if (x < y)
...
What is the expected result? Since -5 converted to unsigned is the
same as unsigned((UINT_MAX + 1) - 5), it's less than UINT_MAX. If
both of them are promoted to 'long', -5 is still less than UINT_MAX
which is positive. If they are promoted to unsigned long, see the
unsigned thing above.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 22 '06 #24
Victor Bazarov wrote:
[..] Since -5 converted to unsigned is the
same as unsigned((UINT_MAX + 1) - 5)[..]
Now that I'm thinking about it again, it's probably implementation-
defined and not that simple... Sounded plausible, didn't it? :-)

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 22 '06 #25
Bo Persson wrote:
>
"Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet
news:ec**********@murdoch.acc.Virginia.EDU...
>Bo Persson wrote:
>>>
"Kai-Uwe Bux" <jk********@gmx.netskrev i meddelandet
news:ec**********@murdoch.acc.Virginia.EDU...
Bo Persson wrote:

>
"Fraser Ross" <fraserATmembers.v21.co.ukskrev i meddelandet
news:11***********@sp6iad.superfeed.net...
>>A suitable implementation is easy enough to make. It surprises
>>me
>>how
>much library code uses pre increment and decrement operators.
>They
>can
>be less efficient.
>>
>Fraser.
>
>
I don't think it is obvious how to select a proper integral type
for
n, when you don't know what type Size might be. In this case, if
n_arg
happens to be negative, converting it to size_t will not work
well.
>
If Size happens to be a class type with a user defined convertion
operator, how do we know what type(s) it will convert to? Signed,
or
unsigned?

Who says that it is necessary to make a guess as to whether Size
converts to
signed or unsigned? What about:

template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
for ( std::size_t i = 0; i < n; ++i ) {
*first = value;
++first;
}
}
Yes, we are getting closer. :-)

My compiler would complain about a signed/unsigned comparison when
Size really is signed.

It should not. Such comparison is handled gracefully by promotion
rules. I
think, the code is required to compile.

It does with a warning, but the result is incorrect. :-(

If Size is ptrdiff_t for example, and n is negative, comparing to a
size_t doesn't work.
You'r right. My bad.

We are on the right track though, and I think this one could work:

template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
if (0 < n) // n must be positive
{
for ( std::size_t count = n; 0 < count; --count ) {
*first = value;
++first;
}
}
}

If we sort out the possibly negative n first, the remaining values
must be convertible to size_t (assuming size_t is the largest unsigned
type :-).
Looks good. Maybe, I would do

template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
if (0 <= n) // n must not be negative
{
for ( std::size_t count = n; 0 < count; --count ) {
*first = value;
++first;
}
}
}

to make it easier for the compiler to optimize the if-statement away if Size
is an unsigned type.
Best

Kai-Uwe Bux
Aug 22 '06 #26
template <class OutputIterator, class Size, class T>
void fill_n (OutputIterator first, Size n, const T& value) {
if (1 <= n) {
size_t m= n;
do {
--m;
*first= value;
++first;
}
while (1 <= m);
}
};
I had roughly the same code. I would have written almost the same as
you after noticing that a for statement can be used. The optimisation
though I wouldn't have known about.

Fraser.

template < typename OutIter, typename Size, typename T >
void fill_n ( OutIter first, Size n, const T & value ) {
if (0 <= n) // n must not be negative
{
for ( std::size_t count = n; 0 < count; --count ) {
*first = value;
++first;
}
}
}

to make it easier for the compiler to optimize the if-statement away
if Size
is an unsigned type.


Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------
http://www.usenet.com
Aug 22 '06 #27

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Anon Email | last post by:
Hi people, I'm learning about header files in C++. The following is code from Bartosz Milewski: // Code const int maxStack = 16; class IStack
27
by: karan.shashi | last post by:
Hey all, I was asked this question in an interview recently: Suppose you have the method signature bool MyPairSum(int array, int sum) the array has all unique values (no repeats), your...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.