From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,9d303864ae4c70ad X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2004-04-10 19:45:35 PST Path: archiver1.google.com!news1.google.com!news.glorb.com!cyclone1.gnilink.net!spamkiller2.gnilink.net!gnilink.net!nwrdny03.gnilink.net.POSTED!0e8a908a!not-for-mail From: Hyman Rosen User-Agent: Mozilla Thunderbird 0.5 (Windows/20040207) X-Accept-Language: en-us, en MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: Expressing physical units (Was: Reprise: 'in out' parameters for functions) References: <5ad0dd8a.0404090512.15af2908@posting.google.com> <5ad0dd8a.0404100507.729d3577@posting.google.com> In-Reply-To: Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Message-ID: Date: Sun, 11 Apr 2004 02:45:34 GMT NNTP-Posting-Host: 68.237.196.35 X-Complaints-To: abuse@verizon.net X-Trace: nwrdny03.gnilink.net 1081651534 68.237.196.35 (Sat, 10 Apr 2004 22:45:34 EDT) NNTP-Posting-Date: Sat, 10 Apr 2004 22:45:34 EDT Xref: archiver1.google.com comp.lang.ada:6964 Date: 2004-04-11T02:45:34+00:00 List-Id: Jacob Sparre Andersen wrote: > It should be noted that my analysis was tied rather strongly to Ada, > and a more relaxed programming language might be able to do something > that would be sufficiently close to full compile-time unit checking. C++ can do full compile-time unit checking with no runtime overhead as long as all units needed by the program are known at compile-time. The technique uses templates, requires automatic instantiation of templates for usability (and so cannot be done in Ada), and was published in Barton & Nackman, _Scientific and Engineering C++_. I've often posted the technique, but here goes again, in a simplified version: template struct Unit { double value; Unit(double value = 0.0) : value(value) { } Unit operator+(Unit other) { return Unit(value + other.value); } }; template Unit operator*(Unit l, Unit r) { return Unit(l.value * r.value); } This supports positive and negative whole number powers. For those rare applications which require fractional powers, you can move to using pairs of numerator/denominator template parameters to represent fractions. The full implementation will include the other operators, and may have the value type as a template parameter as well, but this is enough of a guide to see how it works. Here's how you might write the output operator: template Ostream &operator<<(Ostream &o, const Unit &v) { o << v.value; if (M > 0) o << " g"; if (M > 1) o << "^" << M; if (D > 0) o << " cm"; if (D > 1) o << "^" << D; if (T > 0) o << " s"; if (T > 1) o << "^" << T; if (M < 0 || D < 0 || T < 0) o << " /"; if (M < 0) o << " g"; if (M < 1) o << "^" << -M; if (D < 0) o << " cm"; if (D < 1) o << "^" << -D; if (T < 0) o << " s"; if (T < 1) o << "^" << -T; return o; } Because M, D, T are template parameters, their values are all known at compile time, and the output routine instantiated for a particular unit will contain only the code needed, without any tests at runtime.