Thursday, September 18, 2014

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

comp.lang.c++@googlegroups.com Google Groups
Unsure why you received this message? You previously subscribed to digests from this group, but we haven't been sending them for a while. We fixed that, but if you don't want to get these messages, send an email to comp.lang.c+++unsubscribe@googlegroups.com.
JiiPee <no@notvalid.com>: Sep 18 11:59AM +0100

In all examples of creating a string class they always do it like this:
 
class String
{
public:
// functions
...
private:
char* str;
int len;
};
 
But listening experts they always say that we should not use the old C
array but rather vector. So why String is not done like:
 
class String
{
public:
// functions
...
private:
vector<char> str;
};
 
?
Is it somehow slower? I would actully prefer the vector as its c++.
Its like this in all C++ tutorials.
Wouter van Ooijen <wouter@voti.nl>: Sep 18 01:13PM +0200

JiiPee schreef op 18-Sep-14 12:59 PM:
 
> ?
> Is it somehow slower? I would actully prefer the vector as its c++.
> Its like this in all C++ tutorials.
 
There is an good std::string, so creating a custom (heap based) string
is for educational purposes only.
 
Your first version uses only C-level 'first principles'. It shows how
memory can be allocated on the heap, maybe resized, that you must obey
the rule of (at least) 3 to make things work properly, etc. It shows the
*guts* of how a string class can work.
 
The second version relies on std::vector, which is itself implemented
somewhat like the first version, to do all the dirty work. It might
still be useful to explain the interface of the string, but it hides all
the implementation details.
 
So which one to choose depends on what you want to explain.
 
Wouter van Ooijen
JiiPee <no@notvalid.com>: Sep 18 12:13PM +0100

Ah, sending messages before thinking it through.
 
Obviously needs a character array as C because thats the representation
of strings, we cannot for example "cout<<" a vector.
 
My mistake...I wish I could delete these messages :)
 
On 18/09/2014 11:59, JiiPee wrote:
JiiPee <no@notvalid.com>: Sep 18 12:16PM +0100

On 18/09/2014 12:13, Wouter van Ooijen wrote:
> all the implementation details.
 
> So which one to choose depends on what you want to explain.
 
> Wouter van Ooijen
 
Ok, but I just found out myself that vector is not usefull because we
cannot do:
 
cout<<str;
if str is a vector. So string class must return a char* type pointer,
isnt it? But hmmmm.... can we actually get that char* from vector? I
remember reading that vector can be changed to char*, I remember correctly?
JiiPee <no@notvalid.com>: Sep 18 12:19PM +0100

hmmm, am still actually thinking... as I mentioned, I remember reading
that vector<char> can return a char* pointing to the first character of
the vector... have to study a bit more about it.
 
On 18/09/2014 12:13, JiiPee wrote:
JiiPee <no@notvalid.com>: Sep 18 12:22PM +0100

Okey, but I think that is more like a question that do we need C type
arrays anymore at all?
 
I mean if I am teaching C++ I would like to teach the correct way to do
things. Using a C arrays would teach wrong ways to program C++ , isn't it?
 
On 18/09/2014 12:13, Wouter van Ooijen wrote:
JiiPee <no@notvalid.com>: Sep 18 12:28PM +0100

|This will return char* :
(|char| *)(&str[0])
 
But obviously it can only be return for reading, not modifying the vector.
This would work with the String class in all situations?
|
 
 
 
On 18/09/2014 12:19, JiiPee wrote:
Wouter van Ooijen <wouter@voti.nl>: Sep 18 03:01PM +0200

JiiPee schreef op 18-Sep-14 1:22 PM:
> arrays anymore at all?
 
> I mean if I am teaching C++ I would like to teach the correct way to do
> things. Using a C arrays would teach wrong ways to program C++ , isn't it?
 
That depends.
 
If you want to teach how things work at the lowest level (as opposed to
what one should use): when you get down to the implementation it is
still C-style arrays and pointers.
 
When programming in a resource-rich situation (for instance a PC) using
the STL and other standard libraries is definitely a good idea.
 
In a resource-constraint situation (for instance real-time work on a
small micro-controller) using the same libraries might be a bad idea
because they often use the heap (which you will likely not have), and
have an unpredictable timing. (The *average* performance is generally
very good, but that does not help at all in a strict real-time situation).
 
Wouter van Ooijen
(who happens to be teaching C++)
Ben Bacarisse <ben.usenet@bsb.me.uk>: Sep 18 01:42AM +0100

> { 10 }, // Initialized into i
> { 29.7f } // Initialized into f
> };
 
Did you not just argue against one use of auto because you did not want
the meaning to depend on a detail like the type of a constant? In that
case, there is a chance the compiler will pick up such a mistake later,
but that's not possible with this proposal.
 
<snip>
--
Ben.
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Sep 17 06:53PM -0700

On Wednesday, September 17, 2014 8:42:44 PM UTC-4, Ben Bacarisse wrote:
> > };
 
> Did you not just argue against one use of auto because you did not want
> the meaning to depend on a detail like the type of a constant?
 
The constant in the auto reference had no definition to tie back to, and
was entirely dependent upon its use in the function body for its type,
allowing the error to potentially exist and be uncaught because it has
no correlation due to auto. In this case the definition is provided in
the union members. And while the possibility still exists of making a
mistake and providing the incorrect form in the initializer, it would
be less likely in my estimate because it would require the developer
make two mistakes rather than just one (1-forgetting the proper
declaration in the union, and 2-using an initializer form which could
be readily translated into an existing type).
 
It is still possible though. When you use unions there are some
tradeoffs, and this is one of them (no direct typing, so the
possibility of errors increases).
 
> In that case, there is a chance the compiler will pick up such a
> mistake later, but that's not possible with this proposal.
> Ben.
 
My personal preference would be that all initializers line up exactly,
and if not then generate a compiler error so they must be explicitly
cast to convey original intent.
 
And in the case of there being some ambiguity, such as 5 being used as
an initializer on a union which has both int and char members, and
because the value 5 is within range of both and ambiguity exists, then
they too should be explicitly cast -- unless they both translate into
a compiled byte form which maps to the same memory location within
the union, in which case it is automatically resolved by the
peculiarities of the instance declaration, and the cast becomes
unnecessary.
 
Best regards,
Rick C. Hodgin
Ben Bacarisse <ben.usenet@bsb.me.uk>: Sep 18 01:33PM +0100

> was entirely dependent upon its use in the function body for its type,
> allowing the error to potentially exist and be uncaught because it has
> no correlation due to auto.
 
Though, since the type of the function is affected, it might get caught
later on in the compile. An error in the above can never be caught
because the types are all correct.
 
> make two mistakes rather than just one (1-forgetting the proper
> declaration in the union, and 2-using an initializer form which could
> be readily translated into an existing type).
 
Maybe you did not get what I was referring to. An error (which can't be
caught later on) can be introduced but a single character typo. Only
one mistake is needed.
 
<snip>
> And in the case of there being some ambiguity, such as 5 being used as
> an initializer on a union which has both int and char members, and
> because the value 5 is within range of both and ambiguity exists,
 
5 is "in range" for a very large number of types (especially if the
member has constructors defined). But this is C++ not C, and in C++ the
programmer can differentiate between an int (5) and a char ('\5').
 
<snip>
--
Ben.
seeplus <gizmomaker@bigpond.com>: Sep 17 10:10PM -0700

On Thursday, September 18, 2014 7:58:44 AM UTC+10, Christopher Pisz wrote:
> number of people saying things like, "strong evidence" and "overwhelming
> evidence", but I myself have never in my entire lifetime actually seen
> any evidence, and never will, because it is not observable.
 
You have evolution right in front of your eyes (including the unrequired inside corners) with about 40 now useless vestigial parts still stuck on you, and you also have silly vestigial primate behaviours.
 
e.g. You started as a foetus with a stupid tailbone ... for most people this thankfully reduces to your Coccyx now that you do not have to wrap it around a tree branch.
Quite a few kids retain the actual monkey tail, requiring surgery.
 
Men with tits. Now that is a major "design flaw" but does not look like going away for a long time.
(Evolution == BAD. We would lose those good versions).
 
Appendix. Used by our long ago ancestors for digestion.
Slowly going away but appears to be >>yes!! evolving << to a smaller organ which may have uses in our current environment, doing a different job in the present day man's guts.
 
Nasty Wisdom teeth. Useful for our stinking ancestor's diet, but quickly and
painfully disappearing.
 
Are you losing your little toenail? A lot of people are.
Mine has just about gone.
In a couple of generations that bit will be gone from humans, followed by the toe/s.
I just do not shin up trees.
 
You have many weird vestigial primate behaviours eg You get goose bumps.
 
This really looks like we have evolved from those ugly common ancestors at the zoo, right?
 
Or did that ADAM man just get stuck with these useless bits by a clumsy (pre 98) designer.
Talk about haphazard edit and continue designing.
Paavo Helde <myfirstname@osa.pri.ee>: Sep 17 05:46PM -0500

Robert Hutchings <rm.hutchings@gmail.com> wrote in
 
> LOL. WELL, you guys were right. C++ is NOT fast enough for
> "Ultra-HFT", in which FGPA modules are co-located with the exchanges.
 
Of course we were right, as would have been anybody else who had taken
those 30 seconds to type "HFT C++" into Google.
 
Cheers
Paavo
Christopher Pisz <nospam@notanaddress.com>: Sep 17 06:33PM -0500

On 9/17/2014 3:36 PM, Robert Hutchings wrote:
 
>> So ... why don't you check them out from the code repository?
 
> Yes, I will. I work in a, shall we say, "controlled" environment, so I will have to "request" additional code from our Version Control Admin....
 
Sounds like a hassle. You do realize how in demand C++ programmers are
in the job market, don't you? You've given us little insight into how
your job functions, but if I don't have access to source control and you
want me to figure out other people's code, whom contradict themselves in
their comments (not uncommon) then piss off, because I can find another
job in 2 day's time.
Robert Hutchings <rm.hutchings@gmail.com>: Sep 17 08:49PM -0700

> want me to figure out other people's code, whom contradict themselves in
> their comments (not uncommon) then piss off, because I can find another
> job in 2 day's time.
 
Yes, I tend to agree. Seems to happen frequently...
Victor Bazarov <v.bazarov@comcast.invalid>: Sep 10 02:18PM -0400

On 9/10/2014 8:33 AM, Victor Bazarov wrote:
 
>> I can think of a number of ways to do this, but I don't like any of
>> them. What do you think is the most elegant way to do this?
 
> It must be by means of std::copy.
 
Or perhaps by means of one of c-tors. Standard string has a constructor
from two input iterators (see 21.4.2/14), so if you can convert the
positions into iterators, you could simply construct the string from them.
 
V
--
I do not respond to top-posted replies, please don't ask
Victor Bazarov <v.bazarov@comcast.invalid>: Sep 11 12:05PM -0400

On 9/11/2014 11:58 AM, Christopher Pisz wrote:
 
> std::vector<std::string> test = {"foo","bar"};
 
> I'd like to set up a static const at the top of my cpp to define a
> collection of strings.
 
a) Drop the '='.
b) VC++ 2012 doesn't support that syntax. Get VC++ 2013.
 
V
--
I do not respond to top-posted replies, please don't ask
Noob <nope@nono.com>: Sep 11 04:30PM -0300

Hi there.
 
I'm performing my first experiments in C++ and I'm having a
bit of trouble when trying put the definition of an operator
overloading in a separate file.
 
I understand the example is a bit silly but anyways.
 
The following code when written in a single file will work
and output the desired results:
 
$cat foo_main.cpp
 
#include <iostream>
#include <array>
 
template<typename T, std::size_t SIZE>
std::array<T,SIZE> operator+(const std::array<T,SIZE>& a,
const std::array<T,SIZE>& b)
{
 
std::array<T,SIZE> result;
 
for(unsigned int i = 0; i < a.size(); ++i)
{
result[i] = a[i] + b[i];
}
 
return result;
}
 
 
int main()
{
 
std::array<double, 10> arr1, arr2, arr3;
 
for(unsigned int i = 0; i < arr1.size(); i++)
{
arr1[i] = i;
arr2[i] = 2*i;
 
}
 
arr3 = arr1 + arr2;
 
for(unsigned int i = 0; i < arr3.size(); ++i)
{
std::cout << arr3[i] << std::endl;
}
 
 
}
 
$ g++ --version
g++ (Debian 4.7.2-5) 4.7.2
 
$g++ -std=c++11 foo_main.cpp && ./a.out
0
3
6
9
12
15
18
21
24
27
 
 
Now let
 
$cat foo.h
#ifndef FOO_H_INCLUDED
#define FOO_H_INCLUDED
 
#include <array>
 
template<typename T, std::size_t SIZE>
std::array<T,SIZE> operator+(const std::array<T,SIZE>& a,
const std::array<T,SIZE>& b);
 
 
$ cat foo.cpp
#include <array>
#include "foo.h"
 
template<typename T, std::size_t SIZE>
std::array<T,SIZE> operator+(const std::array<T,SIZE>& a,
const std::array<T,SIZE>& b)
{
 
std::array<T,SIZE> result;
 
for(unsigned int i = 0; i < a.size(); ++i)
{
result[i] = a[i] + b[i];
}
 
return
result;
}
 
$ cat main_split.cpp
#include "foo.h"
#include <iostream>
#include <array>
 
int main()
{
 
std::array<double, 10> arr1, arr2, arr3;
 
for(unsigned int i = 0; i < arr1.size(); i++)
{
arr1[i] = i;
arr2[i] = 2*i;
 
}
 
arr3 = arr1 + arr2;
 
for(unsigned int i = 0; i < arr3.size(); ++i)
{
std::cout << arr3[i] << std::endl;
}
 
 
}
 
$g++ -std=c++11 main_split.cpp foo.cpp
 
/tmp/cczMGm79.o: In function `main':
main_split.cpp:(.text+0xdc): undefined reference to
`std::array<double, 10ul> operator+<double, 10ul>(std::array<double,
10ul> const&, std::array<double, 10ul> const&)'
collect2: error: ld returned 1 exit status
 
 
I don't know what is the problem. I can compile a similar
program declaring simple functions in separate files but not
this particular case.
 
Thanks in advance for any help.
Juha Nieminen <nospam@thanks.invalid>: Sep 12 11:15AM


> return
> result;
> }
 
You need to instantiate it in *this* compilation unit with every
type it's being used with anywhere else.
 
Unfortunately since C++ does not support export templates (anymore),
the compiler won't do it for you. You'll have to do it manually.
 
If you want to do it like that, you need explicit instantiation
(google for "template explicit insantiation").
 
However, the easiest way is to simply do it like you did in your
first example, and put the implementation in the same header file
where the declaration is.
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
Noob <nope@nono.com>: Sep 11 06:03PM -0300

On 09/11/2014 05:12 PM, Paavo Helde wrote:
 
> Actually, once there, better read through the whole FAQ.
 
> Cheers
> Paavo
 
Thank you very much. There's -a lot- of useful information there.
 
In my case, would you recommend me to move the definition of the
template to the header file or to do the second solution shown here:
 
http://www.parashift.com/c++-faq/separate-template-fn-defn-from-decl.html
 
The former seems easy enough but I wouldn't like to make a habit
of it if it happens to be a source of future complications.
 
The latter solution implies in telling the compiler which
instantiations I'll actually need (right?) but I'm not sure
how to deal with it in my case without explicitly declaring a
SIZE.
 
Thanks again.
Paavo Helde <myfirstname@osa.pri.ee>: Sep 12 01:17AM -0500


> In my case, would you recommend me to move the definition of the
> template to the header file or to do the second solution shown here:
 
> http://www.parashift.com/c++-faq/separate-template-fn-defn-from-
decl.html
 
> The former seems easy enough but I wouldn't like to make a habit
> of it if it happens to be a source of future complications.
 
[for the record: the second solution means explicit instantiation of
templates in a single source file]
 
In software development (and probably especially with C++) you will
notice in time that complexity tends to increase "by itself" and fighting
with the complexity is the most important thing to do. So the rule of
thumb is to always prefer the simplest solution if possible, and here the
first solution (putting all templates in header files) is definitely the
simplest one and means least headaches to write and maintain. Many
template libraries are actually header-only (including many parts of
STL), so the compilers are ready to cope with them.
 
Many people see that the first solution actually has several advantages:
no need to guess which instantiations are required by the program, plus
better optimization possibilities for the compiler (as the function
definitions are visible inline). The only downside is that the compiling
times might become larger, to fight this one can just keep the header
files concsice and include them only in source files which actually need
them.
 
I would suggest to use the second solution (explicit instantiation in a
source file) only when you are experienced enough to decide this is a
better solution.
 
Cheers
Paavo
Wouter van Ooijen <wouter@voti.nl>: Sep 12 10:05AM +0200

Paavo Helde schreef op 12-Sep-14 8:17 AM:
 
> I would suggest to use the second solution (explicit instantiation in a
> source file) only when you are experienced enough to decide this is a
> better solution.
 
That advice totally matches the third law of optimization: optimize only
when you know there is a (speed or other) problem. (The first two law's
are of course "don't" and "don't").
 
Wouter
Martijn Lievaart <m@rtij.nl.invlalid>: Sep 12 09:21AM +0200

On Thu, 11 Sep 2014 15:04:01 -0700, kurt krueckeberg wrote:
 
> managed pointer is the raw pointers are only used internally and never
> exposed to clients. The class looks like this. shared_ptr<Node234> seems
> like needless overhead?
 
It would have masked the problem. Using unique_ptr<> would have exposed
the problem more.
 
 
> template<typename K> class Tree234 {
> protected:
...
> public:
> Tree234() { root = nullptr; }
> ~Tree234();
 
Where is operator=() ??
 
M4
Christopher Pisz <nospam@notanaddress.com>: Sep 11 05:18PM -0500

On 9/11/2014 5:12 PM, Mr Flibble wrote:
>> only used internally and never exposed to clients.
 
> No.
 
> /Flibble
 
I agree. Do not use shared pointers or any ref counting types just
because they exist. I've encountered as many circular reference leaks as
I have leaks from raw pointers. Either way, understand and verify when
memory is allocated and when memory is released, even if using a ref
counting or shared pointer, verify it actually got released.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Sep 12 12:03PM +0100

On Fri, 12 Sep 2014 00:43:40 -0700 (PDT)
> type traits only meant to be used for types from the STL and I should
> simply define my own, even if their functionality is basically the
> same?
 
This is an interesting question. On whether you can do it,
§17.6.4.2.1/1 of the C++11 standard states that:
 
"The behavior of a C++ program is undefined if it adds declarations
or definitions to namespace std or to a namespace within namespace std
unless otherwise specified. A program may add a template
specialization for any standard library template to namespace std
only if the declaration depends on a user-defined type and the
specialization meets the standard library requirements for the
original template and is not explicitly prohibited."
 
On 'is_integral' and 'is_arithmetic' in particular, §20.9.2/1 (which
includes those type trait structs) provides that "The behavior of a
program that adds specializations for any of the class templates
defined in this subclause is undefined unless otherwise specified."
This presupposes that there are some type traits amongst these which
are specified elsewhere in the standard as permitted to be specialized,
but I have to say I have not traced what they are, and I should be
interested if you find any. However, they do not appear to include the
ones in which you are interested.
 
Presumably the thinking behind this is that there should never normally
be a need to specialize 'is_integral', 'is_arithmetic' or any of the
other primary or composite type categories in §20.9.4.1 and §20.9.4.2
for user defined types, because these are features that by language
definition only a built-in type can possess. A type is integral if it
meets the definition in §3.9.1/7. It is arithmetic if it meets the
definition in §3.9.1/8.
 
I should have thought it would be less confusing to users of your
library if you provided your own type trait structs for extended
arithmetic types. And I would think it less confusing not to provide
your own type trait which suggests that an extended arithmetic type is
a fundamental type unless in fact it happens to be a typedef for a
fundamental type according to the language definition.
 
Chris
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: