From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5440 invoked by alias); 16 Aug 2008 12:31:35 -0000 Received: (qmail 5431 invoked by uid 22791); 16 Aug 2008 12:31:34 -0000 X-Spam-Check-By: sourceware.org Received: from exprod6og108.obsmtp.com (HELO exprod6og108.obsmtp.com) (64.18.1.21) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sat, 16 Aug 2008 12:30:53 +0000 Received: from source ([192.150.11.134]) by exprod6ob108.postini.com ([64.18.5.12]) with SMTP; Sat, 16 Aug 2008 05:30:50 PDT Received: from inner-relay-1.corp.adobe.com ([153.32.1.51]) by outbound-smtp-1.corp.adobe.com (8.12.10/8.12.10) with ESMTP id m7GCR8G3007488; Sat, 16 Aug 2008 05:27:08 -0700 (PDT) Received: from fe1.corp.adobe.com (fe1.corp.adobe.com [10.8.192.70]) by inner-relay-1.corp.adobe.com (8.12.10/8.12.10) with ESMTP id m7GCUoiq010512; Sat, 16 Aug 2008 05:30:50 -0700 (PDT) Received: from namailgen.corp.adobe.com ([10.8.192.91]) by fe1.corp.adobe.com with Microsoft SMTPSVC(6.0.3790.1830); Sat, 16 Aug 2008 05:30:50 -0700 Received: from 10.7.234.20 ([10.7.234.20]) by namailgen.corp.adobe.com ([10.8.192.91]) via Exchange Front-End Server namail.corp.adobe.com ([10.8.189.100]) with Microsoft Exchange Server HTTP-DAV ; Sat, 16 Aug 2008 12:30:49 +0000 User-Agent: Microsoft-Entourage/12.12.0.080729 Date: Sun, 17 Aug 2008 04:08:00 -0000 Subject: Re: reinterpret_casting a non-POD From: Eljay Love-Jensen To: Philip , GCC-help Message-ID: In-Reply-To: <25c035550808160442n695bb421m79e58ede2d203e0@mail.gmail.com> Mime-version: 1.0 Content-type: text/plain; charset="US-ASCII" Content-transfer-encoding: 7bit X-IsSubscribed: yes Mailing-List: contact gcc-help-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-help-owner@gcc.gnu.org X-SW-Source: 2008-08/txt/msg00156.txt.bz2 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