30

Using typedef in C++ creates an alias for a type.

So:

typedef double Length; typedef double Mass; 

creates two aliases which can be intermixed. In other words we can pass a value of type Mass to a function that expects a value of type Length.

Is there a lightweight way of creating new types? I would like them to be double underneath but be "different" so that one can't be used in place of another.

I would prefer something lighter than creating a new class or struct. Also, I am aware of the dimensions lib in boost. This is more complex and does a lot more than I need.

3
  • If you're into C++-like languages, D's typedef is strong, and its alias is equivalent to the weak typedef of C++. I think typedef is deprecated in D2, unfortunately. Commented Aug 22, 2011 at 4:46
  • possible duplicate of Creating a new primitive type Commented Aug 22, 2011 at 7:06
  • 1
    Not a duplicate: that one specifically asked for implicit conversions, and this question specifically doesn't want them. ("can't be used in place of another"). Commented Aug 22, 2011 at 8:15

4 Answers 4

24

BOOST_STRONG_TYPEDEF seems to be designed exactly for what you're looking for. I believe it does it's magic by creating a class and overloading the operators to make it behave like a builtin type, but I've not looked at it's implementation.

Sign up to request clarification or add additional context in comments.

8 Comments

Ah, I was just going to type out something like that. Once again Boost already has the solution for problems I hadn't even made up :-) I wish C++11 had introduces explicit typedefs, though...
boost.org/doc/libs/1_46_1/boost/strong_typedef.hpp It is basically a macro which generates a customized class. You can easily copy that idea and reuse it in your own code.
+1: true! And yes, it's based on a struct, but uses boost::operators, so a non-boost version would be quite bloated.
I have a strong suspicion it is solved by template metaprogramming.
@vsz: How so? I don't see any TMP going on there.
|
11

While BOOST_STRONG_TYPEDEF is a pretty simple solution, if you're mixing lengths and masses into more complicated units (e.g. in the physical sciences) then you might want to use Boost.Units.

Comments

4

One other possible answer in C++11 is to use enum class : type. This will allow you to do what you want but it has its own downsides. For example you would have to overload a lot of operators.

#include <iostream> #include <string> enum class A : int; enum class B : int; std::ostream& operator<<(std::ostream& os, const A& t){ os << static_cast<int>(t); return os; } std::ostream& operator<<(std::ostream& os, const B& t){ os << static_cast<int>(t); return os; } int test(A t){ std::cout << "A " << t << std::endl; return 0; } int test(B t){ std::cout << "B " << t << std::endl; return 0; } int main(){ A a{static_cast<A>(42)}; B b{static_cast<B>(0)}; test(a); test(b); } 

This would give the output of:

A 42 B 0 

Or you could just get the integer part like this

template<class T> int GetInt(T t) { return static_cast<int>(t); } std::cout << "B " << GetInt(t) << std::endl; 

1 Comment

only good answer on here. No one should ever use boost and c++20... well...
2

If the Metaclasses proposal (p7070) goes through (right now it's still at revision0), then we shall be able to create strong typedefs using an empty metaclass. Proposed syntax:

$class strong_typedef { }; using Length = $double.as(strong_typedef); using Mass = $double.as(strong_typedef); 

Earliest we might see this would be C++20

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.