 |
 |
|
 |
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Today, I wrote a parser in C++.
The slightly alarming thing is that it almost works correctly too. (It's
not quite finished yet.)
And no segfaults! It turns out that if you throw enough STL containers
at the problem, you can make it work without any manual pointer
manipulation. (I shudder to think what the performance is like...
Fortunately the input to the parser will always be small.)
It took 4 employees approximately 4 hours to get VisualStudio to
successfully compile and link the code. (There are external
dependencies, and the program is split into two projects which have to
cross-reference each other correctly, and so on.) VS is really very
clunky with C++ code.
It then took me about half an hour to write the parser test cases, and
the rest of today to write the actual parser. Nested subexpression
parsing still isn't working quiet right yet, so I need to go take a look
at that.
I must say, when I signed up for a job as a C# programmer, I didn't
think I'd spend 3 months writing Bash scripts, two weeks writing
VBScript and then a day writing C++ code... :-P
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On Mon, 13 May 2013 20:09:39 +0200, Orchid Win7 v1 <voi### [at] dev null> wrote:
> Today, I wrote a parser in C++.
>
> I must say, when I signed up for a job as a C# programmer, I didn't
> think I'd spend 3 months writing Bash scripts, two weeks writing
> VBScript and then a day writing C++ code... :-P
Sounds exciting ;)
--
-Nekar Xenos-
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Orchid Win7 v1 <voi### [at] dev null> wrote:
>
> I must say, when I signed up for a job as a C# programmer, I didn't
> think I'd spend 3 months writing Bash scripts, two weeks writing
> VBScript and then a day writing C++ code... :-P
It's the overly-detailed, over-inflated job 'qualifications' requirements :-P
To be a brick-layer these days, the qualifications probably read: "Must be
familiar with silicon/water chemistry on the atomic level, plus five years of
academic training in geometry. Phd in architectural design a plus."
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
> It took 4 employees approximately 4 hours to get VisualStudio to
> successfully compile and link the code. (There are external
> dependencies, and the program is split into two projects which have to
> cross-reference each other correctly, and so on.) VS is really very
> clunky with C++ code.
After having spent a few years with VS and C#, a few months ago I tried
again VS for C++ and agree it's still very clunky in comparison. Not
sure if that's more a limitation of C++ compared to C#, but it's
certainly not as user friendly.
> I must say, when I signed up for a job as a C# programmer, I didn't
> think I'd spend 3 months writing Bash scripts, two weeks writing
> VBScript and then a day writing C++ code... :-P
You mean you haven't found an excuse to use POV yet!?! (and then
obviously the newsgroups as well...)
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Orchid Win7 v1 <voi### [at] dev null> wrote:
> And no segfaults! It turns out that if you throw enough STL containers
> at the problem, you can make it work without any manual pointer
> manipulation.
When using the standard containers, one should know how they work and
what they are doing, in terms of efficiency. For example, passing them
by value eg. as function parameters is inefficient, and that should always
be done by reference, if possible.
And also, of course, use the right tool for the job. It makes no sense
to use, for example, std::list for something that std::vector will do.
And if your array is of static size, use std::array instead of std::vector
(especially if it's eg. a smallish array that's a member variable of a
class that gets instantiated a lot.)
You can still index those out-of-bounds, but many compilers, eg. Visual
Studio, will add boundary checks when compiling in debug mode. (The
boundary checks are not used in release mode for efficiency.)
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
> You mean you haven't found an excuse to use POV yet!?! (and then
> obviously the newsgroups as well...)
Well, I did use my IRTC entry for some of our test data...
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 14/05/2013 06:04 PM, Warp wrote:
> When using the standard containers, one should know how they work and
> what they are doing, in terms of efficiency. For example, passing them
> by value eg. as function parameters is inefficient, and that should always
> be done by reference, if possible.
How about std::string? Presumably it's a bad idea to pass that by value
either...
> And also, of course, use the right tool for the job. It makes no sense
> to use, for example, std::list for something that std::vector will do.
> And if your array is of static size, use std::array instead of std::vector
All this stuff is pretty dynamic. I have no idea how big the expression
I'm parsing will be until after I finish parsing it.
I'm sure if you could see my code, you'd probably have a heart attack
over all the highly inefficient stuff it's doing. Then again, it gets
run once at application start-up, parsing a few dozen strings that are
mostly a dozen characters long each, so...
(Perhaps the biggest inefficiency is having a lot of zero-element
vectors laying around. I have no idea what the space overhead for that
is. But I also have no idea how to avoid it.)
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 13/05/2013 07:09 PM, Orchid Win7 v1 wrote:
> The slightly alarming thing is that it almost works correctly too. (It's
> not quite finished yet.)
At about 2AM, I rolled over in bed and realised why this is broken.
std::vector<Stuff> current = stack.back();
current.push_back(more_stuff);
Uh, yes... that doesn't do what I meant AT ALL! >_<
Still, I'm impressed I managed to figure out the bug when I don't even
have access to the code...
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 13/05/2013 07:09 PM, Orchid Win7 v1 wrote:
> It took 4 employees approximately 4 hours to get VisualStudio to
> successfully compile and link the code.
But that's nothing compared to how long it took to get VS to produce a
DLL, and then get C# to successfully call this DLL without access
violations... >_<
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Orchid Win7 v1 <voi### [at] dev null> wrote:
> On 14/05/2013 06:04 PM, Warp wrote:
> > When using the standard containers, one should know how they work and
> > what they are doing, in terms of efficiency. For example, passing them
> > by value eg. as function parameters is inefficient, and that should always
> > be done by reference, if possible.
> How about std::string? Presumably it's a bad idea to pass that by value
> either...
It depends on the implementation.
Since std::string is so ubiquitous, many standard library implementations
have optimizations that make copying them fast (some use short string
optimization, some use lazy copying...), but that's in no way a guarantee.
There's usually no reason to not to use a std::string reference if it
suffices. Only copy when you have to.
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Orchid Win7 v1 <voi### [at] dev null> wrote:
> spend 3 months writing Bash scripts, two weeks writing
> VBScript and then a day writing C++ code... :-P
you truly suck at bash ;)
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
OK, so I have a class that looks like this:
class Foobar
{
private:
Secrets secrets;
public:
int Foo1();
int Foo2();
int Foo3();
};
Now I want to put that in a header file. What I *actually* want to write is
class Foobar
{
public:
int Foo1();
int Foo2();
int Foo3();
};
However, this doesn't work at all, because now the "real" Foobar class
is a different size to what all the clients of Foobar are expecting.
General mayhem ensues.
So I have to put the entire class definition into the header file. But
that means I have to put Secrets into the header file too - a data
structure that clients have absolutely no reason to know anything about.
(And I have to include everything that Secrets mentions, and everything
that those things mention, and...)
I thought perhaps I could just write an empty forward declaration, but
unsurprisingly that doesn't work; the compiler needs size information.
After Googling it, the only solution I could find was to make the
private field a *pointer* to the secret data. Now I can put a dummy
forward declaration in the header file, and define the real data
structure in the implementation, where it belongs.
And now I'm doing manual memory management. >_<
The example I got from Google shows a class with a constructor and a
destructor - so, following Warp's teachings, my immediate reaction is
"what the hell happens if somebody copies the object?" I fear the
secrets will be double-freed at some point.
My question is... Is there some simple change I might make to the code
to avoid all the gotchas of manual memory management?
I mean, there will only ever be one object, created in one place, so it
"should" be fine... but it still makes me nervous. If some day somebody
tries to use the code in a new way, I don't want it to suddenly fail in
a spectacular way so some poor sod has to spend 3 weeks trying to figure
out why...
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 15/05/2013 12:34 AM, nemesis wrote:
> Orchid Win7 v1<voi### [at] dev null> wrote:
>> spend 3 months writing Bash scripts, two weeks writing
>> VBScript and then a day writing C++ code... :-P
>
> you truly suck at bash ;)
Oh, and I suppose *you* know exactly how to parse the output of sfdisk
to generate a valid mtab entry? :-P
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Orchid Win7 v1 <voi### [at] dev null> wrote:
> On 15/05/2013 12:34 AM, nemesis wrote:
> > Orchid Win7 v1<voi### [at] dev null> wrote:
> >> spend 3 months writing Bash scripts, two weeks writing
> >> VBScript and then a day writing C++ code... :-P
> >
> > you truly suck at bash ;)
>
> Oh, and I suppose *you* know exactly how to parse the output of sfdisk
> to generate a valid mtab entry? :-P
just a joke about the duration of your bash programming versus C++ :)
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Orchid Win7 v1 <voi### [at] dev null> wrote:
> So I have to put the entire class definition into the header file. But
> that means I have to put Secrets into the header file too - a data
> structure that clients have absolutely no reason to know anything about.
If having the internal-implementation-detail as a member variable of
the class is something you just must avoid, and especially if this is
a class that doesn't get instantiated a lot, then the solution is to
use the Pimpl idiom, which regardless of the funny name, is exactly what
you described. In other words, make a forward declaration of that private
class and just have a pointer to it as member.
> My question is... Is there some simple change I might make to the code
> to avoid all the gotchas of manual memory management?
Yes: Use std::shared_ptr instead of a raw pointer. In other words, you do
it like this:
class PrivateClass;
class MyClass
{
std::shared_ptr<PrivateClass> privateObject;
};
Then in the implementation of MyClass just do a:
privateObject = new PrivateClass;
and then you can forget about managing it yourself.
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Warp <war### [at] tag povray org> wrote:
> class PrivateClass;
> class MyClass
> {
> std::shared_ptr<PrivateClass> privateObject;
> };
Oh, and take into account that if instances of MyClass are copied around,
the copies will share the one and same PrivateClass object. That will not
get deep-copied. (That's what the "shared ptr" means, actually.)
If you want to avoid MyClass being copied around, that can be disabled.
(Of course this restricts the ways in which the class can be used, so
it's always a compromise.)
Another possibility is to write a copy constructor and a copy assignment
operator that deep-copies the private object... It all depends on how
exactly you need MyClass to behave.
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
>> class PrivateClass;
>
>> class MyClass
>> {
>> std::shared_ptr<PrivateClass> privateObject;
>> };
OK. That seems easy enough.
> Oh, and take into account that if instances of MyClass are copied around,
> the copies will share the one and same PrivateClass object. That will not
> get deep-copied. (That's what the "shared ptr" means, actually.)
There "should" only ever be one instance of this class; I'd just like to
avoid the program exploding if somebody *does* copy that instance for
some reason. A shallow copy is acceptable.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
> There "should" only ever be one instance of this class; I'd just like to
> avoid the program exploding if somebody *does* copy that instance for
> some reason. A shallow copy is acceptable.
Is there a C++ equivalent to the C# static class? That would ensure at
compile-time that nobody tried to create an(other) instance.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
scott <sco### [at] scott com> wrote:
> > There "should" only ever be one instance of this class; I'd just like to
> > avoid the program exploding if somebody *does* copy that instance for
> > some reason. A shallow copy is acceptable.
> Is there a C++ equivalent to the C# static class? That would ensure at
> compile-time that nobody tried to create an(other) instance.
You could use a namespace instead of a class. Private implementation can
then all go to the source file, away from the header file.
On the other hand, this limits where you can use this "pseudoclass" and
it could be difficult to maintain backwards compatibility if you ever
wanted to change it so that more than one instance could be created.
Of course you could have a class that only has static member functions...
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Le 16/05/2013 17:27, Warp nous fit lire :
> scott <sco### [at] scott com> wrote:
>> Is there a C++ equivalent to the C# static class? That would ensure at
>> compile-time that nobody tried to create an(other) instance.
>
You can either have all methods of a class static, or use a singleton
pattern.
> You could use a namespace instead of a class. Private implementation can
> then all go to the source file, away from the header file.
>
> On the other hand, this limits where you can use this "pseudoclass" and
> it could be difficult to maintain backwards compatibility if you ever
> wanted to change it so that more than one instance could be created.
>
> Of course you could have a class that only has static member functions...
>
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 14/05/2013 06:29 PM, Orchid Win7 v1 wrote:
> But that's nothing compared to how long it took to get VS to produce a
> DLL, and then get C# to successfully call this DLL without access
> violations... >_<
But THAT is nothing compared to the trouble we had trying to build a
Linux "shared object" and getting Mono to load that...
I can still hardly believe that this whole improbable contraption
actually ended up WORKING in the end! o_O
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Le_Forgeron <jgr### [at] free fr> wrote:
> You can either have all methods of a class static, or use a singleton
> pattern.
If you are using an enforced singleton, and you don't want to expose
*any* implementation detail to the outside, one possibility would be
to do this:
//------------------------------------------------------------
// In the header file:
// ------------------
class TheClass
{
public:
virtual void someFunction() = 0;
virtual int anotherFunction(int parameter) = 0;
virtual void aThirdFunction(double, double) = 0;
};
TheClass& theClassInstance();
//------------------------------------------------------------
//------------------------------------------------------------
// In the implementation file:
// --------------------------
#include "TheClass.hh"
namespace
{
class TheActualClass: public TheClass
{
struct InnerType { int a, b; }
int privateMember;
double anotherPrivateMember;
InnerType aThirdPrivateMember;
void privateFunction();
public:
TheActualClass() { /* constructor */ }
virtual void someFunction()
{
// implement it here
}
virtual int anotherFunction(int parameter)
{
// implement it here
}
virtual void aThirdFunction(double, double)
{
// implement it here
}
};
}
TheClass& theClassInstance()
{
static TheActualClass actualClassInstance;
return actualClassInstance;
}
//------------------------------------------------------------
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 16/05/2013 08:39 AM, Orchid Win7 v1 wrote:
>>> class PrivateClass;
>>
>>> class MyClass
>>> {
>>> std::shared_ptr<PrivateClass> privateObject;
>>> };
>
> OK. That seems easy enough.
I entered this into VisualStudio, and it worked great.
However, when I tried to compile it under Linux, GCC refused to accept it.
First, VS seems to somehow allow you to compile things even without
actually importing the necessary include files. (E.g., it will happily
accept std::shared_ptr even though I didn't #include <memory>.) GCC
demands that you actually specify the include files [like you'd expect].
Weird, but true.
Second, it seems this "feature" only exists in C++11. I don't know what
GCC is defaulting to, but apparently you have to add a switch to tell it
to accept C++11. And when I do that, my code compiles perfectly, but the
rest of the codebase breaks spectacularly.
So, in summary, I had to revert everything back to how it was. *sigh*
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 16/05/2013 06:46 PM, Orchid Win7 v1 wrote:
> I can still hardly believe that this whole improbable contraption
> actually ended up WORKING in the end! o_O
The daft thing is, it turns out to actually be pretty easy to write some
C++, make a DLL out of it, and call that from C#. The actual code that
ended up in source control is both small and simple.
This belies the vast amount of man-hours it took to *arrive* at this
final arrangement. It took an absurd amount of Google searches and
trail-and-error to get the myriad of pieces to fit together just right.
In summary, it's easy when you know how. So easy, presumably, that
nobody bothers to write down how it's actually done - so the next person
who tries to do this will have the exact same problem. :-/
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Orchid Win7 v1 <voi### [at] dev null> wrote:
> Second, it seems this "feature" only exists in C++11. I don't know what
> GCC is defaulting to, but apparently you have to add a switch to tell it
> to accept C++11. And when I do that, my code compiles perfectly, but the
> rest of the codebase breaks spectacularly.
> So, in summary, I had to revert everything back to how it was. *sigh*
You could use std::auto_ptr instead of std::shared_ptr, but then you'd
better disable copying for your class.
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 5/17/2013 11:16 AM, Warp wrote:
> Orchid Win7 v1 <voi### [at] dev null> wrote:
>> Second, it seems this "feature" only exists in C++11. I don't know what
>> GCC is defaulting to, but apparently you have to add a switch to tell it
>> to accept C++11. And when I do that, my code compiles perfectly, but the
>> rest of the codebase breaks spectacularly.
>
>> So, in summary, I had to revert everything back to how it was. *sigh*
>
> You could use std::auto_ptr instead of std::shared_ptr, but then you'd
> better disable copying for your class.
>
Or use boost::shared_ptr of course.
Actually, this reminds me that I should update some of my own code from
boost:shared_ptr to std::shared_ptr.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 15/05/2013 10:44 PM, Warp wrote:
> Orchid Win7 v1<voi### [at] dev null> wrote:
>> So I have to put the entire class definition into the header file. But
>> that means I have to put Secrets into the header file too - a data
>> structure that clients have absolutely no reason to know anything about.
>
> If having the internal-implementation-detail as a member variable of
> the class is something you just must avoid, and especially if this is
> a class that doesn't get instantiated a lot, then the solution is to
> use the Pimpl idiom, which regardless of the funny name, is exactly what
> you described. In other words, make a forward declaration of that private
> class and just have a pointer to it as member.
My next question was going to be "is there a way to expose part of a
class so that the test framework can access it, but nothing else can?"
And then I read the documentation for our test framework [GTest, in case
anybody cares], and it says to do basically the same thing as the above.
IOW, make a private class, put it in its own header file, let the test
framework include that header file, but nobody else.
Not sure if it's worth it just to hide one single method, but it might
be useful in other parts of the codebase...
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Orchid Win7 v1 <voi### [at] dev null> wrote:
> And then I read the documentation for our test framework [GTest, in case
> anybody cares], and it says to do basically the same thing as the above.
> IOW, make a private class, put it in its own header file, let the test
> framework include that header file, but nobody else.
In principle if a class or function exists in a namespace that's not
local to a compilation unit (in other words, a nameless namespace inside
a compilation unit), it will be visible globally and could therefore
technically speaking be used by everything else.
Unlike it might seem, header files in C/C++ are not a language feature.
They are not syntax that imposes some kind of semantics (eg. access
restrictions or something like that.) It's not like other code couldn't
use some class or function if it doesn't have access to the header file
that declares them.
Header files are both a convenience and an abstraction tool, but are
strictly speaking unnecessary.
Let's say that you *know* that somewhere in the innards of some compilation
unit (which might be eg. a library) there's a function named 'foo' which
takes an int and returns an int, which is in the global namespace. Even
if you have no access to any header that declares said function, you can
still just write in your own code:
//----------------------------------------------------------------
int foo(int);
void myFunction()
{
foo(5);
}
//----------------------------------------------------------------
With classes it becomes a bit more complicated because you need to
know the exact contents of the class. However, technically speaking
if you know that you don't need any header file to use it.
Of course all this is mostly theoretical.
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
>>> So, in summary, I had to revert everything back to how it was. *sigh*
>>
>> You could use std::auto_ptr instead of std::shared_ptr, but then you'd
>> better disable copying for your class.
>
> Or use boost::shared_ptr of course.
OK, so I went with boost::shared_ptr in the end.
However, I can't seem to figure out what to write in the constructor.
I've got a field that looks like
boost::shared_ptr<std::vector<Foo>> _foo;
What do I need to do to initialise this correctly?
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 20/05/2013 09:15 PM, Warp wrote:
> Of course all this is mostly theoretical.
Yeah. Assuming that my fellow coders aren't *purposely* trying to break
things, I just want to structure the code I'm writing in a way which
minimises the potential for mistakes, that's all.
(We've got some code which is only public so that the test suite can
run. It makes me feel slightly twitchy, but hey...)
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 5/21/2013 10:25 AM, Orchid Win7 v1 wrote:
> However, I can't seem to figure out what to write in the constructor.
> I've got a field that looks like
>
> boost::shared_ptr<std::vector<Foo>> _foo;
>
> What do I need to do to initialise this correctly?
boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
Take a look over the constructors of shared_ptr for more detail. I
should note that it's relatively uncommon that I want a shared_ptr to a
std::vector. Unless you actually need to store _foo somewhere else in
the code it's might be better to just forgo the shared_ptr and pass _foo
by reference to whichever functions need it.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 5/21/2013 10:32 AM, Kevin Wampler wrote:
> On 5/21/2013 10:25 AM, Orchid Win7 v1 wrote:
>> However, I can't seem to figure out what to write in the constructor.
>> I've got a field that looks like
>>
>> boost::shared_ptr<std::vector<Foo>> _foo;
>>
>> What do I need to do to initialise this correctly?
>
>
> boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
>
Oh, and it's probably best to write it like this:
boost::shared_ptr<std::vector<Foo> > _foo(new std::vector<Foo>());
Since some compilers will complain about using >> in a type definition
(due to the ambiguity with the >> operator).
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 21/05/2013 06:32 PM, Kevin Wampler wrote:
> On 5/21/2013 10:25 AM, Orchid Win7 v1 wrote:
>> However, I can't seem to figure out what to write in the constructor.
>> I've got a field that looks like
>>
>> boost::shared_ptr<std::vector<Foo>> _foo;
>>
>> What do I need to do to initialise this correctly?
>
>
> boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
>
> Take a look over the constructors of shared_ptr for more detail. I
> should note that it's relatively uncommon that I want a shared_ptr to a
> std::vector. Unless you actually need to store _foo somewhere else in
> the code it's might be better to just forgo the shared_ptr and pass _foo
> by reference to whichever functions need it.
The only reason I'm doing this is to avoid putting the real definition
of Foo in the header file.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Orchid Win7 v1 <voi### [at] dev null> wrote:
> However, I can't seem to figure out what to write in the constructor.
> I've got a field that looks like
> boost::shared_ptr<std::vector<Foo>> _foo;
> What do I need to do to initialise this correctly?
What do you mean by "field"? Your question is not clear enough.
(And btw, don't start names with an underscore. Those are reserved for
the compiler.)
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 22/05/2013 08:45 PM, Warp wrote:
> Orchid Win7 v1<voi### [at] dev null> wrote:
>> However, I can't seem to figure out what to write in the constructor.
>> I've got a field that looks like
>
>> boost::shared_ptr<std::vector<Foo>> _foo;
>
>> What do I need to do to initialise this correctly?
>
> What do you mean by "field"? Your question is not clear enough.
I mean something like
class Foobar
{
private:
boost::shared_ptr<std::vector<Foo>> foo;
public:
Foobar()
}
> (And btw, don't start names with an underscore. Those are reserved for
> the compiler.)
Hoooookay... In that case, there's about 200 lines in the existing
codebase that need to be changed. o_O
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
>> boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
>
> Oh, and it's probably best to write it like this:
>
> boost::shared_ptr<std::vector<Foo> > _foo(new std::vector<Foo>());
>
> Since some compilers will complain about using >> in a type definition
> (due to the ambiguity with the >> operator).
VisualStudio compiles this perfectly. GCC point-blank fails to compile
it. *sigh* Gotta love the number of inconsistencies between two
compilers for supposedly "the same" language...
(VC emits endless warnings about "printf may be unsafe; please use
printf_s instead". Apparently the latter function doesn't exist in GCC...)
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Le 2013-05-23 03:22, Orchid Win7 v1 a écrit :
>>> boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
>>
>> Oh, and it's probably best to write it like this:
>>
>> boost::shared_ptr<std::vector<Foo> > _foo(new std::vector<Foo>());
>>
>> Since some compilers will complain about using >> in a type definition
>> (due to the ambiguity with the >> operator).
>
> VisualStudio compiles this perfectly. GCC point-blank fails to compile
> it. *sigh* Gotta love the number of inconsistencies between two
> compilers for supposedly "the same" language...
You are surprised that a Microsoft product allows something that is
frowned upon by a more anal-retentive competitor?!?
>
> (VC emits endless warnings about "printf may be unsafe; please use
> printf_s instead". Apparently the latter function doesn't exist in GCC...)
They are MS-specific versions of the functions.
http://msdn.microsoft.com/en-us/library/8ef0s5kh%28v=vs.80%29.aspx
http://msdn.microsoft.com/en-us/library/239ffwa0%28v=vs.80%29.aspx
I'm sure the purists would frown that Microsoft decides to mess with
<sdtio.h> instead of putting them in a "msstdio.h" or similar. Way back
when the dinosaurs still roamed the Earth, I used to hang in comp.lang.c
and I vividly remember certain members being quite angry at Borland for
pretending that conio.h was part of the standard headers and its
functions part of the standard libraries.
--
/*Francois Labreque*/#local a=x+y;#local b=x+a;#local c=a+b;#macro P(F//
/* flabreque */L)polygon{5,F,F+z,L+z,L,F pigment{rgb 9}}#end union
/* @ */{P(0,a)P(a,b)P(b,c)P(2*a,2*b)P(2*b,b+c)P(b+c,<2,3>)
/* gmail.com */}camera{orthographic location<6,1.25,-6>look_at a }
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 5/23/2013 6:27 AM, Francois Labreque wrote:
> Le 2013-05-23 03:22, Orchid Win7 v1 a écrit :
>>>> boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
>>>
>>> Oh, and it's probably best to write it like this:
>>>
>>> boost::shared_ptr<std::vector<Foo> > _foo(new std::vector<Foo>());
>>>
>>> Since some compilers will complain about using >> in a type definition
>>> (due to the ambiguity with the >> operator).
>>
>> VisualStudio compiles this perfectly. GCC point-blank fails to compile
>> it. *sigh* Gotta love the number of inconsistencies between two
>> compilers for supposedly "the same" language...
>
> You are surprised that a Microsoft product allows something that is
> frowned upon by a more anal-retentive competitor?!?
>
Actually, I'm a little surprised that GCC didn't accept it, as that sort
of things should be allowed under the C++11 standard
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html) and
GCC 4.7 is listed as supporting that feature
(http://gcc.gnu.org/gcc-4.7/cxx0x_status.html). In general GCC seems to
have much better C++11 support that MSVC, so it's strange to see an
example of the opposite -- perhaps Andrew's using an old version of GCC
or something.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
>>> boost::shared_ptr<std::vector<Foo> > _foo(new std::vector<Foo>());
>>>
>>> Since some compilers will complain about using >> in a type definition
>>> (due to the ambiguity with the >> operator).
>>
>> VisualStudio compiles this perfectly. GCC point-blank fails to compile
>> it. *sigh* Gotta love the number of inconsistencies between two
>> compilers for supposedly "the same" language...
>
> You are surprised that a Microsoft product allows something that is
> frowned upon by a more anal-retentive competitor?!?
boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
I don't see how the >> is ambiguous at all in this statement. Seems to
me like lazy/bad parser design if this trips it up.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 5/23/2013 7:14 AM, scott wrote:
>
> boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
>
> I don't see how the >> is ambiguous at all in this statement. Seems to
> me like lazy/bad parser design if this trips it up.
>
It's not quite so cut and dry as you might guess. For example:
#include <iostream>
using std::cout;
using std::endl;
int _foo(int i) {
return i;
}
namespace std {
static const int vector = 7;
}
namespace boost {
static const int shared_ptr = 5;
}
int main(int argc, char** argv) {
int Foo = 3;
cout << (boost::shared_ptr<std::vector<Foo>> _foo(NULL)) << endl;
return 0;
}
If you run this program it should print "1" (at least in MSVC), which is
the result of treating < and >> and the less-than and bit-shift
operators. Of course you couldn't write "new std::vector<Foo>()" in
this scheme, but it does show that it's hard to tell what's a template
and what's not at a purely syntatic level.
In any case, the C++11 standard does allow
"boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>()); " and
the most recent version of GCC supposedly supports this. You can read a
bit more about it here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Orchid Win7 v1 <voi### [at] dev null> wrote:
> > What do you mean by "field"? Your question is not clear enough.
> I mean something like
> class Foobar
> {
> private:
> boost::shared_ptr<std::vector<Foo>> foo;
> public:
> Foobar()
> }
Why didn't you say so in the first place?
If you want to initialize that member function in the constructor, use
the constructor's initializer list or just assign to it in the contructor's
body. In the first case:
Foobar::Foobar(): foo(new std::vector<Foo>)
{}
Or if you prefer,
Foobar::Foobar()
{
foo = new std::vector<Foo>;
}
Btw, C++98 does not support >> for closing a double template. You have
to add a space in between.
I'm wondering why you are using a std::vector, though. I thought that what
you wanted was something like this:
//----------------------------------------------------------------
class Foobar
{
struct Impl;
boost::shared_ptr<Impl> impl;
public:
Foobar();
};
//----------------------------------------------------------------
In which case the implementation would be like:
//----------------------------------------------------------------
struct Foobar::Impl
{
std::vector<Foo> array;
}
Foobar::Foobar(): impl(new Impl)
{}
//----------------------------------------------------------------
Much simpler and cleaner that way.
> > (And btw, don't start names with an underscore. Those are reserved for
> > the compiler.)
> Hoooookay... In that case, there's about 200 lines in the existing
> codebase that need to be changed. o_O
I have never quite understood why so many programmers seem to be obsessed
with putting underscores at the beginning of names.
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Kevin Wampler <nob### [at] nowhere net> wrote:
> On 5/21/2013 10:25 AM, Orchid Win7 v1 wrote:
> > However, I can't seem to figure out what to write in the constructor.
> > I've got a field that looks like
> >
> > boost::shared_ptr<std::vector<Foo>> _foo;
> >
> > What do I need to do to initialise this correctly?
> boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
*Where* are you doing that?
If you mean it like this:
class Foobar
{
boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
};
then it works, but only in C++11. I think Andrew needed to do it in C++98.
--
- Warp
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
>> boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
>>
>> I don't see how the >> is ambiguous at all in this statement. Seems to
>> me like lazy/bad parser design if this trips it up.
>
> It's not quite so cut and dry as you might guess. For example:
...
> cout << (boost::shared_ptr<std::vector<Foo>> _foo(NULL)) << endl;
Is that ambiguous?
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 5/23/2013 8:58 AM, scott wrote:
>>> boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
>>>
>>> I don't see how the >> is ambiguous at all in this statement. Seems to
>>> me like lazy/bad parser design if this trips it up.
>>
>> It's not quite so cut and dry as you might guess. For example:
> ...
>> cout << (boost::shared_ptr<std::vector<Foo>> _foo(NULL)) << endl;
>
> Is that ambiguous?
>
Obviously not since it compiles. It is, however, ambiguous unless you
know the types of boost::shared_ptr and std::vector (and you need to
know them during lexical analysis). I wasn't saying that it's
impossible to correctly parse this sort of thing, just that correctly
parsing it is a more non-trivial task than it might at first appear.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 5/23/2013 8:41 AM, Warp wrote:
> Kevin Wampler <nob### [at] nowhere net> wrote:
>> On 5/21/2013 10:25 AM, Orchid Win7 v1 wrote:
>>> However, I can't seem to figure out what to write in the constructor.
>>> I've got a field that looks like
>>>
>>> boost::shared_ptr<std::vector<Foo>> _foo;
>>>
>>> What do I need to do to initialise this correctly?
>
>> boost::shared_ptr<std::vector<Foo>> _foo(new std::vector<Foo>());
>
> *Where* are you doing that?
>
I was just giving him an example to point out that you pass a raw
pointer to the constructor of shared_ptr and assuming that he'd figure
the rest out from there. But you're right that I perhaps should have
been more explicit.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
>> You are surprised that a Microsoft product allows something that is
>> frowned upon by a more anal-retentive competitor?!?
>>
>
> Actually, I'm a little surprised that GCC didn't accept it, as that sort
> of things should be allowed under the C++11 standard
> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html) and
> GCC 4.7 is listed as supporting that feature
> (http://gcc.gnu.org/gcc-4.7/cxx0x_status.html). In general GCC seems to
> have much better C++11 support that MSVC, so it's strange to see an
> example of the opposite -- perhaps Andrew's using an old version of GCC
> or something.
[Our version of] GCC seems to require a command-line switch to enable
C++11 support, so...
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 23/05/2013 04:38 PM, Warp wrote:
> Orchid Win7 v1<voi### [at] dev null> wrote:
>>> What do you mean by "field"? Your question is not clear enough.
>
>> I mean something like
>
>> class Foobar
>> {
>> private:
>> boost::shared_ptr<std::vector<Foo>> foo;
>> public:
>> Foobar()
>> }
>
> Why didn't you say so in the first place?
>
> If you want to initialize that member function in the constructor, use
> the constructor's initializer list or just assign to it in the contructor's
> body. In the first case:
>
> Foobar::Foobar(): foo(new std::vector<Foo>)
> {}
>
> Or if you prefer,
>
> Foobar::Foobar()
> {
> foo = new std::vector<Foo>;
> }
I had hoped it would "just work" the same way it does if it wasn't a
pointer. But it appears that no, you have to make it actually point to
something. (Which is reasonable.) The constructor seems like the most
sensible place to do that.
> Btw, C++98 does not support>> for closing a double template. You have
> to add a space in between.
Yeah, I already discovered that. ;-)
> I'm wondering why you are using a std::vector, though. I thought that what
> you wanted was something like this:
>
> //----------------------------------------------------------------
>
> class Foobar
> {
> struct Impl;
> boost::shared_ptr<Impl> impl;
>
> public:
> Foobar();
> };
> //----------------------------------------------------------------
>
> In which case the implementation would be like:
>
> //----------------------------------------------------------------
> struct Foobar::Impl
> {
> std::vector<Foo> array;
> }
>
> Foobar::Foobar(): impl(new Impl)
> {}
> //----------------------------------------------------------------
>
> Much simpler and cleaner that way.
Ooo, interesting... Yeah, that could work.
>>> (And btw, don't start names with an underscore. Those are reserved for
>>> the compiler.)
>
>> Hoooookay... In that case, there's about 200 lines in the existing
>> codebase that need to be changed. o_O
>
> I have never quite understood why so many programmers seem to be obsessed
> with putting underscores at the beginning of names.
Apparently ReSharper insists that every C# private field begins with an
underscore. I guess when the guys started writing C++, they just copied
that naming convention. After all, it's only a name, right? You can name
your stuff anything you li- oh, OK, maybe not...
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Today, I spent about 2 hours trying to figure out why the hell all the
tests pass when I compile in Debug mode, but two of them fail if I
compile in Release mode.
Literally, every time I run in Debug mode, all the tests pass. It only
fails in Release mode. In particular, that means I can't fire up the
debugger to see why it's failing. You can only debug in Debug mode, and
in Debug mode it works perfectly.
Apparently Google is your friend. After some minimal amount of effort, I
came across a very well-written forum post which helpfully explains that
in Debug mode all variables are guaranteed to be initialised to default
values, whereas in Release mode variables take on whatever random
gibberish happens to be in memory, unless you remember to explicitly
initialise them to something sane.
Ouch. >_<
Now I guess I understand why Java, C#, et al make such a fuss about
insisting on explicit initialisation and / or explicitly specifying
default initialisation rules...
The other fun thing is that C++ allows you to "throw" absolutely
anything. Several places in the code throw std::string, presumably in
the hope that this will result in some helpful error message being printed.
It doesn't. ;-)
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
> [Our version of] GCC seems to require a command-line switch to enable
> C++11 support, so...
In other news, I may have found out why turning this on breaks GTest.
Apparently it's somehow related to a late change to the C++11 spec.
Basically VC doesn't support some feature that got added to the standard
late. (Varadic tuples or something.) That doesn't completely explain why
it compiles just fine without C++11 turned on though...
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
The OTHER fun thing, of course, is when you invoke a template with the
wrong parameters.
Trouble is, the compiler has no idea that the parameters are wrong. All
it knows is that when it tries to expand the template, somewhere several
million miles away from your code a type mismatch happens, or an
operator doesn't exist, or...
This would be acceptable if VC offered some how to find out WHAT
TEMPLATE it was attempting to expand when the error occurred. But no, it
just shows you the source code for the STL (or Boost or whatever) and
points at the line on which the problem was actually detected. There
seems to be no way that I can discover what line of which file resulting
in this template being invoked in the first place - and THAT is surely
where the problem is, not in STL itself.
(E.g., today I erroneously said set<string, string>. It took quite a
while to hunt through the source control history to manually inspect
every template instruction I've recently touched and thus discover the
problem. If I knew, say, WHAT FILE to look in, it might be faster...)
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |