How should I box integer types in C++?
Suppose my code has
using foo = int32_t;
somewhere, and
using bar = int32_t;
then, for some reason, I need to distinguish between this type and other int32_ts (and their aliases). But - I still want them to behave just like int32_ts.
Now, I can write:
struct foo int32_t value;
struct bar int32_t value;
which distinguishes between the types. But - these structs don't behave like ints at all; I can't even compare foos to each others! (Well, not before C++20 anyway)
Since int32_t is not a class, I can't do:
struct foo : public int32_t
although that would give me exactly what I need.
So it seems what I want to achieve is a "boxing" (a-la Java, C# etc.) of plain integers into classes, and the rest will be taken care of by inheritance.
It's certainly possible to blurt out a lot of boilerplate and implement all of the relevant operators for integers: assignment, comparison, arithmetic, etc. But, you know, DRY!
If I could override operator dot, that could save me all the code, but that proposal is stuck and doesn't look like it'll go somewhere soon.
So is there something else I could leverage to avoid all of that boilerplate?
c++ integer class-design idiomatic boxed-types
|
show 6 more comments
Suppose my code has
using foo = int32_t;
somewhere, and
using bar = int32_t;
then, for some reason, I need to distinguish between this type and other int32_ts (and their aliases). But - I still want them to behave just like int32_ts.
Now, I can write:
struct foo int32_t value;
struct bar int32_t value;
which distinguishes between the types. But - these structs don't behave like ints at all; I can't even compare foos to each others! (Well, not before C++20 anyway)
Since int32_t is not a class, I can't do:
struct foo : public int32_t
although that would give me exactly what I need.
So it seems what I want to achieve is a "boxing" (a-la Java, C# etc.) of plain integers into classes, and the rest will be taken care of by inheritance.
It's certainly possible to blurt out a lot of boilerplate and implement all of the relevant operators for integers: assignment, comparison, arithmetic, etc. But, you know, DRY!
If I could override operator dot, that could save me all the code, but that proposal is stuck and doesn't look like it'll go somewhere soon.
So is there something else I could leverage to avoid all of that boilerplate?
c++ integer class-design idiomatic boxed-types
2
Sounds like an XY problem to me.
– Zereges
Nov 15 '18 at 21:46
You cannot distinguish thefooandbaraliases.
– Jesper Juhl
Nov 15 '18 at 21:51
When you say you can't compare them, do you mean you want to compare afooto abar? That seems to go against you wanting to distinguish between them a bit. Or do you just meanfootofooandbartobar?
– Kevin
Nov 15 '18 at 21:52
What you're talking about is a totally foreign concept in C++. I'm not sure it's possible.
– Mark Ransom
Nov 15 '18 at 21:54
2
Is this something like what you're trying to do? boost.org/doc/libs/1_65_0/doc/html/boost_units.html
– Mark Ransom
Nov 15 '18 at 21:56
|
show 6 more comments
Suppose my code has
using foo = int32_t;
somewhere, and
using bar = int32_t;
then, for some reason, I need to distinguish between this type and other int32_ts (and their aliases). But - I still want them to behave just like int32_ts.
Now, I can write:
struct foo int32_t value;
struct bar int32_t value;
which distinguishes between the types. But - these structs don't behave like ints at all; I can't even compare foos to each others! (Well, not before C++20 anyway)
Since int32_t is not a class, I can't do:
struct foo : public int32_t
although that would give me exactly what I need.
So it seems what I want to achieve is a "boxing" (a-la Java, C# etc.) of plain integers into classes, and the rest will be taken care of by inheritance.
It's certainly possible to blurt out a lot of boilerplate and implement all of the relevant operators for integers: assignment, comparison, arithmetic, etc. But, you know, DRY!
If I could override operator dot, that could save me all the code, but that proposal is stuck and doesn't look like it'll go somewhere soon.
So is there something else I could leverage to avoid all of that boilerplate?
c++ integer class-design idiomatic boxed-types
Suppose my code has
using foo = int32_t;
somewhere, and
using bar = int32_t;
then, for some reason, I need to distinguish between this type and other int32_ts (and their aliases). But - I still want them to behave just like int32_ts.
Now, I can write:
struct foo int32_t value;
struct bar int32_t value;
which distinguishes between the types. But - these structs don't behave like ints at all; I can't even compare foos to each others! (Well, not before C++20 anyway)
Since int32_t is not a class, I can't do:
struct foo : public int32_t
although that would give me exactly what I need.
So it seems what I want to achieve is a "boxing" (a-la Java, C# etc.) of plain integers into classes, and the rest will be taken care of by inheritance.
It's certainly possible to blurt out a lot of boilerplate and implement all of the relevant operators for integers: assignment, comparison, arithmetic, etc. But, you know, DRY!
If I could override operator dot, that could save me all the code, but that proposal is stuck and doesn't look like it'll go somewhere soon.
So is there something else I could leverage to avoid all of that boilerplate?
c++ integer class-design idiomatic boxed-types
c++ integer class-design idiomatic boxed-types
edited Nov 15 '18 at 22:21
einpoklum
asked Nov 15 '18 at 21:42
einpoklumeinpoklum
35.5k27130254
35.5k27130254
2
Sounds like an XY problem to me.
– Zereges
Nov 15 '18 at 21:46
You cannot distinguish thefooandbaraliases.
– Jesper Juhl
Nov 15 '18 at 21:51
When you say you can't compare them, do you mean you want to compare afooto abar? That seems to go against you wanting to distinguish between them a bit. Or do you just meanfootofooandbartobar?
– Kevin
Nov 15 '18 at 21:52
What you're talking about is a totally foreign concept in C++. I'm not sure it's possible.
– Mark Ransom
Nov 15 '18 at 21:54
2
Is this something like what you're trying to do? boost.org/doc/libs/1_65_0/doc/html/boost_units.html
– Mark Ransom
Nov 15 '18 at 21:56
|
show 6 more comments
2
Sounds like an XY problem to me.
– Zereges
Nov 15 '18 at 21:46
You cannot distinguish thefooandbaraliases.
– Jesper Juhl
Nov 15 '18 at 21:51
When you say you can't compare them, do you mean you want to compare afooto abar? That seems to go against you wanting to distinguish between them a bit. Or do you just meanfootofooandbartobar?
– Kevin
Nov 15 '18 at 21:52
What you're talking about is a totally foreign concept in C++. I'm not sure it's possible.
– Mark Ransom
Nov 15 '18 at 21:54
2
Is this something like what you're trying to do? boost.org/doc/libs/1_65_0/doc/html/boost_units.html
– Mark Ransom
Nov 15 '18 at 21:56
2
2
Sounds like an XY problem to me.
– Zereges
Nov 15 '18 at 21:46
Sounds like an XY problem to me.
– Zereges
Nov 15 '18 at 21:46
You cannot distinguish the
foo and bar aliases.– Jesper Juhl
Nov 15 '18 at 21:51
You cannot distinguish the
foo and bar aliases.– Jesper Juhl
Nov 15 '18 at 21:51
When you say you can't compare them, do you mean you want to compare a
foo to a bar? That seems to go against you wanting to distinguish between them a bit. Or do you just mean foo to foo and bar to bar?– Kevin
Nov 15 '18 at 21:52
When you say you can't compare them, do you mean you want to compare a
foo to a bar? That seems to go against you wanting to distinguish between them a bit. Or do you just mean foo to foo and bar to bar?– Kevin
Nov 15 '18 at 21:52
What you're talking about is a totally foreign concept in C++. I'm not sure it's possible.
– Mark Ransom
Nov 15 '18 at 21:54
What you're talking about is a totally foreign concept in C++. I'm not sure it's possible.
– Mark Ransom
Nov 15 '18 at 21:54
2
2
Is this something like what you're trying to do? boost.org/doc/libs/1_65_0/doc/html/boost_units.html
– Mark Ransom
Nov 15 '18 at 21:56
Is this something like what you're trying to do? boost.org/doc/libs/1_65_0/doc/html/boost_units.html
– Mark Ransom
Nov 15 '18 at 21:56
|
show 6 more comments
2 Answers
2
active
oldest
votes
There is one way I have tried (but not heavily tested) to avoid repeating the boilerplate. It uses templates to easily make a new type simply by supplying a different number as a template parameter. The resulting type can be type aliased to get rid of the ugly template definition:
namespace alt
template<std::size_t TypeId, typename Number>
class typed_number
public:
explicit typed_number(Number n): n(n)
typed_number(typed_number const& tn): n(tn.n)
typed_number& operator= (typed_number const& tn) this->n = tn.n; return *this;
typed_number& operator+=(typed_number const& tn) this->n += tn.n; return *this;
typed_number& operator-=(typed_number const& tn) this->n -= tn.n; return *this;
typed_number& operator*=(typed_number const& tn) this->n *= tn.n; return *this;
typed_number& operator/=(typed_number const& tn) this->n /= tn.n; return *this;
explicit operator Number() const return n;
bool operator==(typed_number tn) const return this->n == tn;
bool operator!=(typed_number tn) const return this->n != tn;
bool operator<=(typed_number tn) const return this->n <= tn;
bool operator>=(typed_number tn) const return this->n >= tn;
bool operator< (typed_number tn) const return this->n < tn;
bool operator> (typed_number tn) const return this->n > tn;
typed_number operator+(typed_number const& tn) const return typed_number(this->n + tn.n);
typed_number operator-(typed_number const& tn) const return typed_number(this->n - tn.n);
typed_number operator*(typed_number const& tn) const return typed_number(this->n * tn.n);
typed_number operator/(typed_number const& tn) const return typed_number(this->n / tn.n);
friend std::ostream& operator<<(std::ostream& os, typed_number<TypeId, Number> n)
return os << n.n;
friend std::istream& operator>>(std::istream& is, typed_number<TypeId, Number>& n)
return is >> n.n;
private:
Number n;
;
// namespace alt
// give each incompatible type a different index
using dollars = alt::typed_number<0, int>;
using cents = alt::typed_number<1, int>;
int main()
auto d1 = dollars(5);
auto d2 = dollars(9);
auto d3 = d1 + d2;
std::cout << d1 << " + " << d2 << " = " << d3 << 'n';
You create the boilerplate once as a template class and instantiate it as different types merely by supplying a unique index as the first template parameter.
I meant avoiding even this. I'm sure there has to be some standard library or boost code which does basically the same thing.
– einpoklum
Nov 15 '18 at 22:32
instead of number one shall pass another class template<typename Tag, typename Number> class typed_number... class dollars_tag; class cents_tag; using dollars = alt::typed_number<dollars_tag, int>; using cents = alt::typed_number<cents_tag, int>;
– Pavlo Mur
Nov 15 '18 at 22:32
@PavloMur My code that I copied this from does exactly as you suggest. However I thought this was simpler and conveyed the basic concept.
– Galik
Nov 15 '18 at 22:44
@einpoklum This only has to be done once. All your other types can be created as template instantiations with no boilerplate at all.
– Galik
Nov 15 '18 at 22:45
add a comment |
Strong typedefs
Several on-and-off-site comments (including @HenriMenke) have brought up the term "strong typedef"s. C++ typedefs are "weak" - they define indistinguishable aliases. A strong typedef of a new type T as type U would make T behave like U, while not having type U.
What you want to do is define two "strong typedefs" of foo and of bar as int's.
There are at least two common strong-typedef, uh, libraries I guess you could say:
- Foonathan's
type_safe(repo on GitHub): Providests::integer<T> - Boost's
strong typdef, which is older and macro-based
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53328298%2fhow-should-i-box-integer-types-in-c%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
There is one way I have tried (but not heavily tested) to avoid repeating the boilerplate. It uses templates to easily make a new type simply by supplying a different number as a template parameter. The resulting type can be type aliased to get rid of the ugly template definition:
namespace alt
template<std::size_t TypeId, typename Number>
class typed_number
public:
explicit typed_number(Number n): n(n)
typed_number(typed_number const& tn): n(tn.n)
typed_number& operator= (typed_number const& tn) this->n = tn.n; return *this;
typed_number& operator+=(typed_number const& tn) this->n += tn.n; return *this;
typed_number& operator-=(typed_number const& tn) this->n -= tn.n; return *this;
typed_number& operator*=(typed_number const& tn) this->n *= tn.n; return *this;
typed_number& operator/=(typed_number const& tn) this->n /= tn.n; return *this;
explicit operator Number() const return n;
bool operator==(typed_number tn) const return this->n == tn;
bool operator!=(typed_number tn) const return this->n != tn;
bool operator<=(typed_number tn) const return this->n <= tn;
bool operator>=(typed_number tn) const return this->n >= tn;
bool operator< (typed_number tn) const return this->n < tn;
bool operator> (typed_number tn) const return this->n > tn;
typed_number operator+(typed_number const& tn) const return typed_number(this->n + tn.n);
typed_number operator-(typed_number const& tn) const return typed_number(this->n - tn.n);
typed_number operator*(typed_number const& tn) const return typed_number(this->n * tn.n);
typed_number operator/(typed_number const& tn) const return typed_number(this->n / tn.n);
friend std::ostream& operator<<(std::ostream& os, typed_number<TypeId, Number> n)
return os << n.n;
friend std::istream& operator>>(std::istream& is, typed_number<TypeId, Number>& n)
return is >> n.n;
private:
Number n;
;
// namespace alt
// give each incompatible type a different index
using dollars = alt::typed_number<0, int>;
using cents = alt::typed_number<1, int>;
int main()
auto d1 = dollars(5);
auto d2 = dollars(9);
auto d3 = d1 + d2;
std::cout << d1 << " + " << d2 << " = " << d3 << 'n';
You create the boilerplate once as a template class and instantiate it as different types merely by supplying a unique index as the first template parameter.
I meant avoiding even this. I'm sure there has to be some standard library or boost code which does basically the same thing.
– einpoklum
Nov 15 '18 at 22:32
instead of number one shall pass another class template<typename Tag, typename Number> class typed_number... class dollars_tag; class cents_tag; using dollars = alt::typed_number<dollars_tag, int>; using cents = alt::typed_number<cents_tag, int>;
– Pavlo Mur
Nov 15 '18 at 22:32
@PavloMur My code that I copied this from does exactly as you suggest. However I thought this was simpler and conveyed the basic concept.
– Galik
Nov 15 '18 at 22:44
@einpoklum This only has to be done once. All your other types can be created as template instantiations with no boilerplate at all.
– Galik
Nov 15 '18 at 22:45
add a comment |
There is one way I have tried (but not heavily tested) to avoid repeating the boilerplate. It uses templates to easily make a new type simply by supplying a different number as a template parameter. The resulting type can be type aliased to get rid of the ugly template definition:
namespace alt
template<std::size_t TypeId, typename Number>
class typed_number
public:
explicit typed_number(Number n): n(n)
typed_number(typed_number const& tn): n(tn.n)
typed_number& operator= (typed_number const& tn) this->n = tn.n; return *this;
typed_number& operator+=(typed_number const& tn) this->n += tn.n; return *this;
typed_number& operator-=(typed_number const& tn) this->n -= tn.n; return *this;
typed_number& operator*=(typed_number const& tn) this->n *= tn.n; return *this;
typed_number& operator/=(typed_number const& tn) this->n /= tn.n; return *this;
explicit operator Number() const return n;
bool operator==(typed_number tn) const return this->n == tn;
bool operator!=(typed_number tn) const return this->n != tn;
bool operator<=(typed_number tn) const return this->n <= tn;
bool operator>=(typed_number tn) const return this->n >= tn;
bool operator< (typed_number tn) const return this->n < tn;
bool operator> (typed_number tn) const return this->n > tn;
typed_number operator+(typed_number const& tn) const return typed_number(this->n + tn.n);
typed_number operator-(typed_number const& tn) const return typed_number(this->n - tn.n);
typed_number operator*(typed_number const& tn) const return typed_number(this->n * tn.n);
typed_number operator/(typed_number const& tn) const return typed_number(this->n / tn.n);
friend std::ostream& operator<<(std::ostream& os, typed_number<TypeId, Number> n)
return os << n.n;
friend std::istream& operator>>(std::istream& is, typed_number<TypeId, Number>& n)
return is >> n.n;
private:
Number n;
;
// namespace alt
// give each incompatible type a different index
using dollars = alt::typed_number<0, int>;
using cents = alt::typed_number<1, int>;
int main()
auto d1 = dollars(5);
auto d2 = dollars(9);
auto d3 = d1 + d2;
std::cout << d1 << " + " << d2 << " = " << d3 << 'n';
You create the boilerplate once as a template class and instantiate it as different types merely by supplying a unique index as the first template parameter.
I meant avoiding even this. I'm sure there has to be some standard library or boost code which does basically the same thing.
– einpoklum
Nov 15 '18 at 22:32
instead of number one shall pass another class template<typename Tag, typename Number> class typed_number... class dollars_tag; class cents_tag; using dollars = alt::typed_number<dollars_tag, int>; using cents = alt::typed_number<cents_tag, int>;
– Pavlo Mur
Nov 15 '18 at 22:32
@PavloMur My code that I copied this from does exactly as you suggest. However I thought this was simpler and conveyed the basic concept.
– Galik
Nov 15 '18 at 22:44
@einpoklum This only has to be done once. All your other types can be created as template instantiations with no boilerplate at all.
– Galik
Nov 15 '18 at 22:45
add a comment |
There is one way I have tried (but not heavily tested) to avoid repeating the boilerplate. It uses templates to easily make a new type simply by supplying a different number as a template parameter. The resulting type can be type aliased to get rid of the ugly template definition:
namespace alt
template<std::size_t TypeId, typename Number>
class typed_number
public:
explicit typed_number(Number n): n(n)
typed_number(typed_number const& tn): n(tn.n)
typed_number& operator= (typed_number const& tn) this->n = tn.n; return *this;
typed_number& operator+=(typed_number const& tn) this->n += tn.n; return *this;
typed_number& operator-=(typed_number const& tn) this->n -= tn.n; return *this;
typed_number& operator*=(typed_number const& tn) this->n *= tn.n; return *this;
typed_number& operator/=(typed_number const& tn) this->n /= tn.n; return *this;
explicit operator Number() const return n;
bool operator==(typed_number tn) const return this->n == tn;
bool operator!=(typed_number tn) const return this->n != tn;
bool operator<=(typed_number tn) const return this->n <= tn;
bool operator>=(typed_number tn) const return this->n >= tn;
bool operator< (typed_number tn) const return this->n < tn;
bool operator> (typed_number tn) const return this->n > tn;
typed_number operator+(typed_number const& tn) const return typed_number(this->n + tn.n);
typed_number operator-(typed_number const& tn) const return typed_number(this->n - tn.n);
typed_number operator*(typed_number const& tn) const return typed_number(this->n * tn.n);
typed_number operator/(typed_number const& tn) const return typed_number(this->n / tn.n);
friend std::ostream& operator<<(std::ostream& os, typed_number<TypeId, Number> n)
return os << n.n;
friend std::istream& operator>>(std::istream& is, typed_number<TypeId, Number>& n)
return is >> n.n;
private:
Number n;
;
// namespace alt
// give each incompatible type a different index
using dollars = alt::typed_number<0, int>;
using cents = alt::typed_number<1, int>;
int main()
auto d1 = dollars(5);
auto d2 = dollars(9);
auto d3 = d1 + d2;
std::cout << d1 << " + " << d2 << " = " << d3 << 'n';
You create the boilerplate once as a template class and instantiate it as different types merely by supplying a unique index as the first template parameter.
There is one way I have tried (but not heavily tested) to avoid repeating the boilerplate. It uses templates to easily make a new type simply by supplying a different number as a template parameter. The resulting type can be type aliased to get rid of the ugly template definition:
namespace alt
template<std::size_t TypeId, typename Number>
class typed_number
public:
explicit typed_number(Number n): n(n)
typed_number(typed_number const& tn): n(tn.n)
typed_number& operator= (typed_number const& tn) this->n = tn.n; return *this;
typed_number& operator+=(typed_number const& tn) this->n += tn.n; return *this;
typed_number& operator-=(typed_number const& tn) this->n -= tn.n; return *this;
typed_number& operator*=(typed_number const& tn) this->n *= tn.n; return *this;
typed_number& operator/=(typed_number const& tn) this->n /= tn.n; return *this;
explicit operator Number() const return n;
bool operator==(typed_number tn) const return this->n == tn;
bool operator!=(typed_number tn) const return this->n != tn;
bool operator<=(typed_number tn) const return this->n <= tn;
bool operator>=(typed_number tn) const return this->n >= tn;
bool operator< (typed_number tn) const return this->n < tn;
bool operator> (typed_number tn) const return this->n > tn;
typed_number operator+(typed_number const& tn) const return typed_number(this->n + tn.n);
typed_number operator-(typed_number const& tn) const return typed_number(this->n - tn.n);
typed_number operator*(typed_number const& tn) const return typed_number(this->n * tn.n);
typed_number operator/(typed_number const& tn) const return typed_number(this->n / tn.n);
friend std::ostream& operator<<(std::ostream& os, typed_number<TypeId, Number> n)
return os << n.n;
friend std::istream& operator>>(std::istream& is, typed_number<TypeId, Number>& n)
return is >> n.n;
private:
Number n;
;
// namespace alt
// give each incompatible type a different index
using dollars = alt::typed_number<0, int>;
using cents = alt::typed_number<1, int>;
int main()
auto d1 = dollars(5);
auto d2 = dollars(9);
auto d3 = d1 + d2;
std::cout << d1 << " + " << d2 << " = " << d3 << 'n';
You create the boilerplate once as a template class and instantiate it as different types merely by supplying a unique index as the first template parameter.
edited Nov 16 '18 at 3:10
answered Nov 15 '18 at 22:16
GalikGalik
34.6k35281
34.6k35281
I meant avoiding even this. I'm sure there has to be some standard library or boost code which does basically the same thing.
– einpoklum
Nov 15 '18 at 22:32
instead of number one shall pass another class template<typename Tag, typename Number> class typed_number... class dollars_tag; class cents_tag; using dollars = alt::typed_number<dollars_tag, int>; using cents = alt::typed_number<cents_tag, int>;
– Pavlo Mur
Nov 15 '18 at 22:32
@PavloMur My code that I copied this from does exactly as you suggest. However I thought this was simpler and conveyed the basic concept.
– Galik
Nov 15 '18 at 22:44
@einpoklum This only has to be done once. All your other types can be created as template instantiations with no boilerplate at all.
– Galik
Nov 15 '18 at 22:45
add a comment |
I meant avoiding even this. I'm sure there has to be some standard library or boost code which does basically the same thing.
– einpoklum
Nov 15 '18 at 22:32
instead of number one shall pass another class template<typename Tag, typename Number> class typed_number... class dollars_tag; class cents_tag; using dollars = alt::typed_number<dollars_tag, int>; using cents = alt::typed_number<cents_tag, int>;
– Pavlo Mur
Nov 15 '18 at 22:32
@PavloMur My code that I copied this from does exactly as you suggest. However I thought this was simpler and conveyed the basic concept.
– Galik
Nov 15 '18 at 22:44
@einpoklum This only has to be done once. All your other types can be created as template instantiations with no boilerplate at all.
– Galik
Nov 15 '18 at 22:45
I meant avoiding even this. I'm sure there has to be some standard library or boost code which does basically the same thing.
– einpoklum
Nov 15 '18 at 22:32
I meant avoiding even this. I'm sure there has to be some standard library or boost code which does basically the same thing.
– einpoklum
Nov 15 '18 at 22:32
instead of number one shall pass another class template<typename Tag, typename Number> class typed_number... class dollars_tag; class cents_tag; using dollars = alt::typed_number<dollars_tag, int>; using cents = alt::typed_number<cents_tag, int>;
– Pavlo Mur
Nov 15 '18 at 22:32
instead of number one shall pass another class template<typename Tag, typename Number> class typed_number... class dollars_tag; class cents_tag; using dollars = alt::typed_number<dollars_tag, int>; using cents = alt::typed_number<cents_tag, int>;
– Pavlo Mur
Nov 15 '18 at 22:32
@PavloMur My code that I copied this from does exactly as you suggest. However I thought this was simpler and conveyed the basic concept.
– Galik
Nov 15 '18 at 22:44
@PavloMur My code that I copied this from does exactly as you suggest. However I thought this was simpler and conveyed the basic concept.
– Galik
Nov 15 '18 at 22:44
@einpoklum This only has to be done once. All your other types can be created as template instantiations with no boilerplate at all.
– Galik
Nov 15 '18 at 22:45
@einpoklum This only has to be done once. All your other types can be created as template instantiations with no boilerplate at all.
– Galik
Nov 15 '18 at 22:45
add a comment |
Strong typedefs
Several on-and-off-site comments (including @HenriMenke) have brought up the term "strong typedef"s. C++ typedefs are "weak" - they define indistinguishable aliases. A strong typedef of a new type T as type U would make T behave like U, while not having type U.
What you want to do is define two "strong typedefs" of foo and of bar as int's.
There are at least two common strong-typedef, uh, libraries I guess you could say:
- Foonathan's
type_safe(repo on GitHub): Providests::integer<T> - Boost's
strong typdef, which is older and macro-based
add a comment |
Strong typedefs
Several on-and-off-site comments (including @HenriMenke) have brought up the term "strong typedef"s. C++ typedefs are "weak" - they define indistinguishable aliases. A strong typedef of a new type T as type U would make T behave like U, while not having type U.
What you want to do is define two "strong typedefs" of foo and of bar as int's.
There are at least two common strong-typedef, uh, libraries I guess you could say:
- Foonathan's
type_safe(repo on GitHub): Providests::integer<T> - Boost's
strong typdef, which is older and macro-based
add a comment |
Strong typedefs
Several on-and-off-site comments (including @HenriMenke) have brought up the term "strong typedef"s. C++ typedefs are "weak" - they define indistinguishable aliases. A strong typedef of a new type T as type U would make T behave like U, while not having type U.
What you want to do is define two "strong typedefs" of foo and of bar as int's.
There are at least two common strong-typedef, uh, libraries I guess you could say:
- Foonathan's
type_safe(repo on GitHub): Providests::integer<T> - Boost's
strong typdef, which is older and macro-based
Strong typedefs
Several on-and-off-site comments (including @HenriMenke) have brought up the term "strong typedef"s. C++ typedefs are "weak" - they define indistinguishable aliases. A strong typedef of a new type T as type U would make T behave like U, while not having type U.
What you want to do is define two "strong typedefs" of foo and of bar as int's.
There are at least two common strong-typedef, uh, libraries I guess you could say:
- Foonathan's
type_safe(repo on GitHub): Providests::integer<T> - Boost's
strong typdef, which is older and macro-based
answered Nov 16 '18 at 9:21
einpoklumeinpoklum
35.5k27130254
35.5k27130254
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53328298%2fhow-should-i-box-integer-types-in-c%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
Sounds like an XY problem to me.
– Zereges
Nov 15 '18 at 21:46
You cannot distinguish the
fooandbaraliases.– Jesper Juhl
Nov 15 '18 at 21:51
When you say you can't compare them, do you mean you want to compare a
footo abar? That seems to go against you wanting to distinguish between them a bit. Or do you just meanfootofooandbartobar?– Kevin
Nov 15 '18 at 21:52
What you're talking about is a totally foreign concept in C++. I'm not sure it's possible.
– Mark Ransom
Nov 15 '18 at 21:54
2
Is this something like what you're trying to do? boost.org/doc/libs/1_65_0/doc/html/boost_units.html
– Mark Ransom
Nov 15 '18 at 21:56