Re: reinterpret_casting a non-POD

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Philip,

I think the risks are...

*** Pointer aliasing may cause you problems.

*** Intra-structure padding may cause you problems.

*** Alignment requirements that are not fulfilled by your "acquire memory"
may cause you problems.

*** Even if it works on your machine, the non-portable code may cause you
problems if you ever port it, including upgrading compilers from the same
vendor on the same platform.

*** If the class is a general purpose SDK class, I'd strongly consider *not*
making the member functions inline, rather move their implementation out
into the Point.cpp file.  (If your downstream users are a captive audience,
such as you are making an SDK for your own team, or making an SDK which is
only used intra-company, then the issue is much less important.)  Plus, for
a general purpose SDK, I would implement the synthetic routines that the
compiler will generate for you, such as destructor, copy constructor, and
assignment operator, yada yada.  (I'd even go as far as consider the "next
step" and change Point to an interface-only class with virtual functions and
a static factory function, with the implementation class not exposed in the
SDK API.)

#define SOAPBOX

I'd fix those problems by trying to encapsulate the behavior you are trying
to do into the Point class itself.

I don't know what your preferred paradigm for getters/setters naming
convention, so I used the Objective-C / Cocoa -ish one.

I also added the Print/Scan and Write/Read pairs.  And the I/O streaming <<
and >> operator glue.

---------------------------------------- Point.h
// Probably not the best way to get a float NaN.
float const FloatNaN = 0.0f / 0.0f;

class Point
{
  float m[3];
public:
  Point() { m[0] = m[1] = m[2] = FloatNaN; }
  Point(float x, float y, float z) { m[0] = x; m[1] = y; m[2] = z; }
  float* AsFloatArray3() { return m; } // Exposes implementation.
  float X() const { return m[0]; }
  float Y() const { return m[1]; }
  float Z() const { return m[2]; }
  void SetX(float x) { m[0] = x; }
  void SetY(float y) { m[1] = y; }
  void SetZ(float z) { m[2] = z; }
  void Print(std::ostream&) const; // Human readable printer.
  void Scan(std::istream&); // Round-trip scan-from-print.
  void Write(std::ostream&) const; // Binary writer.
  void Read(std::istream&); // Binary reader.
};

inline
std::ostream& operator << (std::ostream& output, Point const& point)
{
  point.Print(output);
  return output;
}

inline
std::istream& operator >> (std::istream& input, Point& point)
{
  point.Scan(input);
  return input;
}
----------------------------------------

Here are some principles:

Put the code in your class, so that for the USERS of your class, it's easy
to use like butter.  Even if that means your class's implementation is ugly
in spots, it is better for the ugliness to be encapsulated in the class
rather than distributed amongst the users.  That's the primary target
audience of your class's API.

The primary target audience of your class's code is the poor maintenance
programmer (could be your future self a few years down the road) who has to
figure out your class, enhance your class, or debug it.  Make your class as
programmer friendly as possible.  Lots of useful comments.  Nice, consistent
formatting.  Don't make statements unnecessarily convoluted.  Trust the
compiler's optimizer.  The only time you should employ "befuddling code" is
if profiling indicates that -- for performance reasons -- the code needs to
have loops manually unrolled or some other heinous obfuscation techniques.
Make sure those manual machinations are well documented, and maybe keep the
"slow" routine around for sanity checking and self-testing.  [The above
Point class is *NOT* a showcase example of programmer friendly formatting.
But it's a pretty simple example, where making it "programmer friendly"
would make it look bloated with unnecessary busy-comments.  Good for
increasing kLOC, if you are paid by the kLOC.]

#undef SOAPBOX

HTH,
--Eljay


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux