How should I box integer types in C++?










0















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?










share|improve this question



















  • 2





    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











  • 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






  • 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















0















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?










share|improve this question



















  • 2





    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











  • 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






  • 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













0












0








0








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?










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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











  • 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





    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











  • 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






  • 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












2 Answers
2






active

oldest

votes


















2














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.






share|improve this answer

























  • 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


















0














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): Provides ts::integer<T>

  • Boost's strong typdef, which is older and macro-based





share|improve this answer






















    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
    );



    );













    draft saved

    draft discarded


















    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









    2














    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.






    share|improve this answer

























    • 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















    2














    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.






    share|improve this answer

























    • 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













    2












    2








    2







    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.






    share|improve this answer















    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.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    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

















    • 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













    0














    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): Provides ts::integer<T>

    • Boost's strong typdef, which is older and macro-based





    share|improve this answer



























      0














      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): Provides ts::integer<T>

      • Boost's strong typdef, which is older and macro-based





      share|improve this answer

























        0












        0








        0







        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): Provides ts::integer<T>

        • Boost's strong typdef, which is older and macro-based





        share|improve this answer













        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): Provides ts::integer<T>

        • Boost's strong typdef, which is older and macro-based






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 16 '18 at 9:21









        einpoklumeinpoklum

        35.5k27130254




        35.5k27130254



























            draft saved

            draft discarded
















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            27

            Top Tejano songwriter Luis Silva dead of heart attack at 64

            Category:Rhetoric