3

How do you create type copies? For example, how do I create types Mass, Acceleration and Force which are not implicitly convertible to double(or any other numeric type), but otherwise have all the characteristics of a double. This would allow a compile-time input validity check for this function:

Force GetForceNeeded(Mass m, Acceleration a);

ensuring that GetForceNeeded can only be called with arguments of type Mass and Acceleration.

Of course, I could achieve this by manually creating a copy of the type:

class Force final
{
public:
//overload all operators
private:
double value;
};

but this is cumbersome. Is there a generic solution?

Pradhan
  • 16,391
  • 3
  • 44
  • 59
  • 2
    Maybe a template? Or use Boost.Units? – Kerrek SB Dec 29 '14 at 17:14
  • @KerrekSB But how do I expose all the operations defined? Say I want to do it for a `string`? – Pradhan Dec 29 '14 at 17:15
  • @Columbo Reading up on strong typedefs! This might do it. Thanks! – Pradhan Dec 29 '14 at 17:15
  • Typedefs can be used. – Unbreakable Dec 29 '14 at 17:16
  • You are not providing any value by wrapping doubles into classes, beside a name. Use typedefs as suggested. – Samuel Dec 29 '14 at 17:18
  • @Samuel That's not true at all. As explained in the question, they provide semantic checks. Just look at the `GetForceNeeded` function. If the inputs were both `double`, I could end up switching the `Mass` and `Acceleration` arguments and the compiler would be happy. (Ok, for this function it makes no difference because `F=ma`, but the point stands.) – Pradhan Dec 29 '14 at 17:19
  • @Pradhan. Then you need implicit conversions: http://en.cppreference.com/w/cpp/language/implicit_cast – Samuel Dec 29 '14 at 17:21
  • The downvotes here are quite funny btw - after Columbo pointed me to strong typedefs, I came across [this well-received question](http://stackoverflow.com/questions/9211210/using-strong-typedef-as-a-more-lightweight-alternative-to-boost-parameter-librar) which is along similar lines. – Pradhan Dec 29 '14 at 17:21
  • 1
    http://programmers.stackexchange.com/questions/243154/c-strongly-typed-typedef – R Sahu Dec 29 '14 at 17:27
  • Kerrek SB had the right solution: Boost.Units. You specifically do NOT want the same operations. It doesn't make sense to add a Mass and an Acceleration, but it does make sense to multiply them. Don't try to work this out yourself, Boost.Units allows all sensible operations and only those (which admittedly is a bit of an issue in fluid mechanics) – MSalters Dec 29 '14 at 18:10
  • @MSalters The variables I chose to illustrate are a bit misleading I guess. I am not trying to do this with physical units or dimensional analysis. I am looking for just a way to create a new type which behaves exactly like another type but isn't implicitly convertible to it. I would want to be able to do this `using_strong EmailAddress = std::string;`, for example. – Pradhan Dec 29 '14 at 18:14

1 Answers1

5

As many commentators have pointed out, one solution is to use BOOST_STRONG_TYPEDEF which provides all the features requested in the question. And here's example usage from their docs:

#include <boost/serialization/strong_typedef.hpp>


BOOST_STRONG_TYPEDEF(int, a)
void f(int x);  // (1) function to handle simple integers
void f(a x);    // (2) special function to handle integers of type a 
int main(){
    int x = 1;
    a y;
    y = x;      // other operations permitted as a is converted as necessary
    f(x);       // chooses (1)
    f(y);       // chooses (2)
}    typedef int a;

There is a proposal to add opaque typedefs to C++1y.

(I am leaving this answer as I can't find an exact dupe. Please flag if that isn't the case.)

Pradhan
  • 16,391
  • 3
  • 44
  • 59