0

I want to be able to use compile time information to prevent two objects of the same class being combined. In particular if a represents meters, and b uses centimeters I want the compiler to not allow their combination.

Can I do this with protected inheritance? Do I need to use Tags?

Something like this?

struct Meters{};
struct Centimeters{};

template < typename Units >
class DimensionedLength : protected Length {
 // What do I need to put in here?
}

int main(){

{
 Length a(0.0), b(1.0), c(2.0);

 std::cout << a+b << std::endl; // fine
 std::cout << a+c << std::endl; // fine
}


{
 DimensionedLength<Meters> a(0.0), b(1.0);
 DimensionedLength<Centimeters> c(2.0);

 std::cout << a+b << std::endl; // fine
 std::cout << a+c << std::endl; // compile error!
}

 return 1;
}

1 Answers1

1

First of all the class template should look like this:

template<typename Units>
struct DimensionedDouble {
    double value;
};

and then you need to implement all the arithmetic operators for it, i.e.:

template<typename Units>
DimensionedDouble<Units> operator+(DimensionedDouble<Units> x, DimensionedDouble<Units> y) {
    return {x.value + y.value};
}

and so on. The overload can only be called when the Units match, otherwise there will be an error.

Depending on how close you want to get the syntax to the fundamental type's, you might also want to add constructors from double, etc., to your class. As shown above, only aggregate initialization from double (with {...} or = {...}) is possible.

walnut
  • 21,629
  • 4
  • 23
  • 59
  • Thanks for the comment, I had tried to simplify things and just made it more confusing. I fixed the question to try incorporate a bit more information, in particular there is a class from an external library that I am trying to wrap which is a little more complicated than double (Eigen::Vector3d if that means anything). – rhetorical5 Dec 26 '19 at 12:46
  • searching a bit further based on your response, would something like this work? https://stackoverflow.com/questions/3058561/how-do-i-make-a-class-whose-interface-matches-double-but-upon-which-templates-c – rhetorical5 Dec 26 '19 at 12:49
  • @rhetorical5 No that answer does not prevent adding differently tagged types at all. – walnut Dec 26 '19 at 12:56
  • @rhetorical5 If you want to reliably prevent implicit conversion between the types or back to the underlying type, you need to copy the whole interface in the way I showed you. There is no other way. What you want is also known as a "strong type". – walnut Dec 26 '19 at 12:58