Tuesday, May 5, 2015

Digest for comp.lang.c++@googlegroups.com - 25 updates in 6 topics

Christopher Pisz <nospam@notanaddress.com>: May 05 10:37AM -0500

On 5/5/2015 10:24 AM, Stefan Ram wrote:
 
> void f( V * & q ){ ::std::cout << q->i << '\n'; }
 
> int main(){ V * p = nullptr; f( p ); }
 
> »q« is a reference, and it /is/ null!
 
No, q is a reference to a pointer that exists, and the pointer is null.
 
 
--
I have chosen to troll filter/ignore all subthreads containing the
words: "Rick C. Hodgins", "Flibble", and "Islam"
So, I won't be able to see or respond to any such messages
---
Alain Ketterlin <alain@universite-de-strasbourg.fr.invalid>: May 05 05:46PM +0200


> void f( V * & q ){ ::std::cout << q->i << '\n'; }
 
> int main(){ V * p = nullptr; f( p ); }
 
> »q« is a reference, and it /is/ null!
 
No. q is a reference to a pointer, and the pointer's value is nullptr.
I.e., q refers to something that exists in a valid state (the variable p
of main). In the body of f(), writing "q = ...any pointer to a V..." is
perfectly ok. What you do instead is: accessing the value pointed to by
the pointer referenced by q. The former part (accessing the value
pointed to...) is faulty, the latter (the pointer referenced by q) is
valid.
 
You can still create an invalid reference:
 
V * p = nullptr;
V & q = *p;
 
but imho the initialization has undefined behavior because you
dereference an invalid pointer (even though you do not really
dereference it).
 
-- Alain.
Mel <mel@zzzzz.com>: May 05 06:07PM +0200


> void f( V * & q ){ ::std::cout << q->i << '\n'; }
 
 
> int main(){ V * p = nullptr; f( p ); }
 
 
> »q« is a reference, and it /is/ null!
 
Nope, q is not null, rather pointer which it refers...
 
--
Press any key to continue or any other to quit
Melzzzzz <mel@zzzzz.com>: May 05 06:55PM +0200

On 5 May 2015 16:26:57 GMT
> something that can be understood by all those who can guess what the
> intended meaning is, but might not be true by a strict reading of the
> wording.
 
You don't understand at all what references are about.
You could write void f(V *q) and get same result....
Paavo Helde <myfirstname@osa.pri.ee>: May 04 11:28PM -0500

Doug Mika <dougmmika@gmail.com> wrote in
> Afterall the decleration of map states that it takes a binary
> predicate, then why isn't it an object of a functor
> (ReverseSort<int>()) instead of just a type (ReverseSort<int>)??
 
Because templates are instantiated with a type (or a compile-time
integral constant, but this does not apply here). An object is not a
type. Type is a compile-time concept and object is a run-time concept,
and template instantiation happens at compile time only.
 
Maybe you are confusing the template parameter with the map constructor
parameter. The map constructor indeed has a comp parameter for taking the
comparator object. By default it uses a default-constructed object of the
relevant type, but you can pass it also explicitly:
 
map<int, string, ReverseSort<int> > myMap
(someOtherMap.cbegin(), someOtherMap.cend(), ReverseSort<int>());
 
Note the parens near the end.
 
hth
Paavo
Victor Bazarov <v.bazarov@comcast.invalid>: May 05 08:36AM -0400

On 5/4/2015 6:40 PM, Doug Mika wrote:
> }
 
> The problem is with my template function ReverseSort<int>, but why
> can't I include it as the binary predicate in map?
 
What does your compiler say? Can you not take a hint from its error
message?
 
ReverseSort<int> is not a type, you can't use it as the third argument
to the 'std::map' template.
 
V
--
I do not respond to top-posted replies, please don't ask
Doug Mika <dougmmika@gmail.com>: May 05 08:06AM -0700

So let me see if I understand this correctly. Template Classes are instantiated with a type, not an object...that makes sense. So I just have to remember that when instantiating a template, I have to use the type NOT an object...and Paavo's explenation made sense.
 
Now however, let's say that as my binary predicate for the map decleration I would like to use a template FUNCTION (not a template CLASS). That is, as my predicate I would like to use the following function:
 
template<typename KeyType>
bool ReverseSort(const KeyType& key1, const KeyType& key2){
return (key1 > key2);
}
 
Since this is a template function not a template object, how would I declare a map to use this function as it's binary predicate?
 
None of the ones below work? Why?
map<int, string, ReverseSort> mapIntToString (someOtherMap.cbegin(), someOtherMap.cend());
 
map<int, string> mapIntToString3 (mapIntToString1.cbegin(), mapIntToString1.cend(),ReverseSort<int>);
 
map<int, string> mapIntToString3 (mapIntToString1.cbegin(), mapIntToString1.cend(),ReverseSort);
legalize+jeeves@mail.xmission.com (Richard): May 05 03:06PM

[Please do not mail me a copy of your followup]
 
Doug Mika <dougmmika@gmail.com> spake the secret code
 
>and NOT
 
>map<int, string, ReverseSort<int>() > someOtherMap
>(someOtherMap.cbegin(), someOtherMap.cend());
 
Templates arguments can be types or an integral or enumeration type
value.[1]
 
std::map takes four template parameters:
- class Key
- class T
- class Compare = std::less<Key>
- class Allocator = std::allocator<std::pair<const Key, T>>
 
ReverseSort is defined as:
 
template<typename KeyType>
struct ReverseSort{
bool operator()(const KeyType& key1, const KeyType& key2){
return (key1 > key2);
}
};
 
ReverseSort<int> is a type, an instantiation of the template struct
ReverseSort with a template argument of int.
 
ReverseSort<int>() is an (anonymous) instance of the type
ReverseSort<int>.
 
Templates cannot take instances of objects as template arguments, only
types or integral values.
 
[1] This is slightly simplified, see 14.3.2 Template non-type
arguments in the standard for details.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
Doug Mika <dougmmika@gmail.com>: May 05 08:36AM -0700

Yes, so how would I instantiate a map object if I wanted to use the following template FUNCTION as my sort predicate:
 
template<typename KeyType>
bool ReverseSort(const KeyType& key1, const KeyType& key2){
return (key1 > key2);
}
 
???
Victor Bazarov <v.bazarov@comcast.invalid>: May 05 11:50AM -0400

On 5/5/2015 11:06 AM, Doug Mika wrote:
> So let me see if I understand this correctly. Template Classes are
instantiated with a type, not an object...that makes sense. So I just
have to remember that when instantiating a template, I have to use the
type NOT an object...and Paavo's explenation made sense.
 
> Now however, let's say that as my binary predicate for the map
decleration I would like to use a template FUNCTION (not a template
CLASS). That is, as my predicate I would like to use the following function:
> bool ReverseSort(const KeyType& key1, const KeyType& key2){
> return (key1 > key2);
> }
 
That's not a *function*. It's a *function template*. You can't *use*
this one, you can only instantiate it and use an instantiation.
 
 
> Since this is a template function not a template object, how would I
declare a map to use this function as it's binary predicate?
> map<int, string, ReverseSort> mapIntToString (someOtherMap.cbegin(), someOtherMap.cend());
 
> map<int, string> mapIntToString3 (mapIntToString1.cbegin(), mapIntToString1.cend(),ReverseSort<int>);
 
> map<int, string> mapIntToString3 (mapIntToString1.cbegin(), mapIntToString1.cend(),ReverseSort);
 
All class templates that use comparators are implemented in such a way
that a function cannot be use do instantiate those templates. You need
either a lambda or a functor.
 
V
--
I do not respond to top-posted replies, please don't ask
Victor Bazarov <v.bazarov@comcast.invalid>: May 05 11:59AM -0400

On 5/5/2015 11:36 AM, Doug Mika wrote:
> Yes, so how would I instantiate a map object if I wanted to use the
following template FUNCTION as my sort predicate:
> return (key1 > key2);
> }
 
> ???
 
I keep forgetting about 'function' template...
 
See if this works for you:
 
#include <string>
#include <map>
#include <functional>
#include <iostream>
 
using namespace std;
 
template<typename KeyType>
bool ReverseSort(const KeyType& key1, const KeyType& key2){
return (key1 > key2);
}
 
int main()
{
//The Program
map<int, string, function<bool(const int&, const int&)>>
mapIntToString1(ReverseSort<int>);
 
mapIntToString1[1] = "one";
mapIntToString1[2] = "two";
mapIntToString1[3] = "three";
mapIntToString1[4] = "four";
 
for (auto m : mapIntToString1)
{ cout << m.first << "," << m.second << endl; }
}
 
V
--
I do not respond to top-posted replies, please don't ask
legalize+jeeves@mail.xmission.com (Richard): May 05 04:09PM

[Please do not mail me a copy of your followup]
 
Victor Bazarov <v.bazarov@comcast.invalid> spake the secret code
 
> map<int, string, function<bool(const int&, const int&)>>
> mapIntToString1(ReverseSort<int>);
 
That works. Details of std::function template class:
<http://en.cppreference.com/w/cpp/utility/functional/function>
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
Doug Mika <dougmmika@gmail.com>: May 05 09:51AM -0700

Yes that worked nicely, and I'll admit, I haven't yet read about the std::function template but I hope someone could quickly explain the following line:
 
map<int, string, function<bool(const int&, const int&)>>
mapIntToString1(ReverseSort<int>);
 
function<bool(const int&, const int&)> - defines type as function that takes two int's and returns a bool. Check
 
mapIntToString1(ReverseSort<int>) - calls the constructor of map that takes key_compare as argument, in this case a function pointer. Is this correct?
ram@zedat.fu-berlin.de (Stefan Ram): May 05 03:05PM

Can someone explain why the type ::std::initializer_list
does not have some convenience members that some programmers
might expect? IIRC, it's members can be stored in ROM, but
why does an ::std::initializer_list l has
 
l.begin()
::std::begin( l )
 
but no
 
l.cbegin()
::std::cbegin( l )
 
, and why is there no
 
l[ size_t ]
l.at( size_t )
 
?
ram@zedat.fu-berlin.de (Stefan Ram): May 05 03:17PM

When a value is returned, its expression is automatically
considered to be an rvalue and thus is /moved/ from although
the literal meaning in early C++ once might have been that
its value is being copied. This is known as "return value
optimization" ("RVO").
 
Does the same apply to arguments in the following sense?
When a function f has a plain ::std::string parameter and
is called
 
f( "a"s + "b"s )
 
, then »"a"s + "b"s« is a temporary, so it does not have to
be copied from but can be moved from. Is this guaranteed to
happen? Is there a name for this "optimization" (akin to "RVO")?
 
So, if it is guaranteed that it will happen for
 
f( ::std::string const s )
 
, then one does not need to write
 
f( ::std::string && s )
 
. Then, what are the use-cases for »f( ::std::string && s )«?
 
PS: I wrote the following program trying to see which
constructors are invoked under the C++ implementation used:
 
#include <ostream>
#include <initializer_list>
#include <memory>
 
struct V
{
V( ::std::initializer_list< int >const l ): use{ *::std::begin( l )}
{ ::std::cout << "V( ::std::initializer_list< int >const l )\n"; }
 
V( V const & other ): use{ other.use }
{ ::std::cout << "V( V const & other )\n"; }
 
V( V && other ): use{ other.use }{ ::std::cout << "V( V && other )\n"; }
 
int use; };
 
void f( V const v )
{ ::std::cout << "f( V const v )" << '\n';
::std::cout << v.use << '\n'; }
 
void g( V && v )
{ ::std::cout << "g( V && const v )" << '\n';
::std::cout << v.use << '\n'; }
 
int main()
{ f( V{ 2 } );
g( V{ 2 } ); }
 
 
V( ::std::initializer_list< int >const l )
f( V const v )
2
V( ::std::initializer_list< int >const l )
g( V && const v )
2
 
In this case, one cannot see any difference between when the
value parameter in »f« and the rvalue parameter in »g« is
being used.
ram@zedat.fu-berlin.de (Stefan Ram): May 05 03:24PM

When asked for the difference between pointers and references
some say that references cannot be null. I know what this is
/intended/ to mean, but the wording might not correctly convey
this for readers who do not yet known this. For an example how
this can be (mis)understood, I show the following program that
has a reference that /is/ null!
 
#include <iostream>
#include <ostream>
 
struct V { int i; };
 
void f( V * & q ){ ::std::cout << q->i << '\n'; }
 
int main(){ V * p = nullptr; f( p ); }
 
»q« is a reference, and it /is/ null!
ram@zedat.fu-berlin.de (Stefan Ram): May 05 04:07PM

>I hope you're not going to ask next why pointers and arrays don't have
>members like 'cbegin' or 'rend'...
 
Well, for arrays ...
 
#include <iostream>
#include <ostream>
#include <memory>
#include <vector>
 
int main()
{ ::std::cout << __cplusplus << '\n';
::std::vector< int >a{ 1, 2, 3 };
for( auto p = ::std::cbegin( a ); p != ::std::cend( a ); ++p )
::std::cout << *p << '\n'; }
 
201402
1
2
3
 
And all of a sudden, it also works with initializer lists!
 
My problem was actually that I did not manage before to force
my compiler into C++14 mode before!
 
#include <iostream>
#include <ostream>
#include <memory>
#include <initializer_list>
 
int main()
{ ::std::cout << __cplusplus << '\n';
::std::initializer_list< int >a{ 1, 2, 3 };
for( auto p = ::std::cbegin( a ); p != ::std::cend( a ); ++p )
::std::cout << *p << '\n'; }
 
201402
1
2
3
ram@zedat.fu-berlin.de (Stefan Ram): May 05 04:26PM

>Nope, q is not null, rather pointer which it refers...
 
The following prints »true«.
 
#include <iostream>
#include <ostream>
#include <ios>
 
struct V { int i; };
 
void f( V * & q ){ ::std::cout << ::std::boolalpha <<( q == 0 )<< '\n'; }
 
int main(){ V * p = nullptr; f( p ); }
 
Saying, »q is not null«, when in fact »q == 0« /is/ true, is something
that can be understood by all those who can guess what the intended
meaning is, but might not be true by a strict reading of the wording.
ram@zedat.fu-berlin.de (Stefan Ram): May 05 04:42PM

>>::std::vector< int >a{ 1, 2, 3 };
>>for( auto p = ::std::cbegin( a ); p != ::std::cend( a ); ++p )
>Yes, but those are not *members*.
 
Oops! I did want to actually /use/ arrays. You already
replied as if I did, but for correctness' sake I'd like
to show the actual working code with an actual array:
 
int a[]{ 1, 2, 3 };
for( auto p = ::std::cbegin( a ); p != ::std::cend( a ); ++p )
 
BTW, there's a paper by, IIRC, Sutter (et al.?), where they
suggest a "uniform call syntax", IIRC, that was to enable
the member call syntax even for non-members.
Victor Bazarov <v.bazarov@comcast.invalid>: May 05 11:30AM -0400

On 5/5/2015 11:05 AM, Stefan Ram wrote:
 
> l[ size_t ]
> l.at( size_t )
 
> ?
 
Most likely *because* those were deemed unnecessary or unnecessarily
difficult to implement. An initializer list is not a container. Its
purpose is to assist initialization, that's all.
 
I hope you're not going to ask next why pointers and arrays don't have
members like 'cbegin' or 'rend'...
 
Besides, the rationales behind language design decisions are discussed
in comp.std.c++. Consider posting there, if you are really interested
and not just venting some kind of frustration, OK?
 
V
--
I do not respond to top-posted replies, please don't ask
Victor Bazarov <v.bazarov@comcast.invalid>: May 05 12:35PM -0400

On 5/5/2015 12:07 PM, Stefan Ram wrote:
> { ::std::cout << __cplusplus << '\n';
> ::std::vector< int >a{ 1, 2, 3 };
> for( auto p = ::std::cbegin( a ); p != ::std::cend( a ); ++p )
 
Yes, but those are not *members*.
 
> 1
> 2
> 3
 
V
--
I do not respond to top-posted replies, please don't ask
Juha Nieminen <nospam@thanks.invalid>: May 05 10:18AM

> long long, not as long. The standard says int64_t must be a typedef, but
> does not say of which type. And it cannot be a typedef of long and long
> long at the same time - these are required to be different types.
 
That doesn't really explain why foo(short(123)) compiles just fine
even though neither version of the function is an exact match, and
either one could be a valid match. Clearly short is a distinct type
from int32_t and int64_t (yet it matches int32_t unambiguously).
 
I don't understand why a 64-bit long can't match int64_t given that
they are identical in size and signedness.
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
legalize+jeeves@mail.xmission.com (Richard): May 05 02:58PM

[Please do not mail me a copy of your followup]
 
Vir Campestris <vir.campestris@invalid.invalid> spake the secret code
 
>> foo(static_cast<std::int64_t>(123));
 
>I don't see why this would make it compile OK giving it 123,
 
123 is the argument to static_cast<> which explicitly promotes the
integral constant 123 to the type std::int64_t and the overload for
that type is selected.
 
>but not
>123L. (you snipped "Note that if I call foo(123) it does not
>give any error.")
 
123 is an integer literal with no type suffix. An integer literal
with no type suffix tells the compiler to pick the smallest type that
can hold the literal. For a decimal literal with no suffix, the type
chosen is the first of int, long int, or long long int that can hold
the value[1]. In your case, this is int. std::int32_t on your
implementation is apparently a typedef for int. So calling foo(123)
does work, but it doesn't call the 64-bit overload.
 
[1] See section 2.14.2 Integer Literals in the standard
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
Cholo Lennon <chololennon@hotmail.com>: May 05 10:27AM -0300

On 05/04/2015 04:35 AM, koolAMit wrote:
>> writing C++ code. It looks like C# to me, which is a completely
>> different language.
 
> Ya Its C#, I thought Some one knows it, So I post it.
 
You should post in "microsoft.public.dotnet.languages.csharp"
 
 
--
Cholo Lennon
Bs.As.
ARG
FredK <fred.l.kleinschmidt@gmail.com>: May 05 07:50AM -0700

On Tuesday, May 5, 2015 at 6:28:10 AM UTC-7, Cholo Lennon wrote:
 
> > Ya Its C#, I thought Some one knows it, So I post it.
 
> You should post in "microsoft.public.dotnet.languages.csharp"
 
The main problem seems to be that the body of GetFriendsOfDegree()
has not been written.
--
Fred K
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: