Use cases for std::add_const and similar












23















Some type transformations in <type_traits> can also be expressed using core language syntax (e.g. std::add_const<T>::type is/seems equivalent to const T). Dtto for std::add_lvalue_reference, and perhaps others. What is the use for these type traits?



I fully understand the standard would be providing an "incomplete toolbox" without them, and I can imagine use in a meta way, something like this:



template<typename In, template <typename> class Modifier>
struct Apply {
typedef typename Modifier<T>::type Out;
};

Apply<int, std::add_const>


Are there any other use cases for these traits which can be expressed syntactically, or are they just included "out of a sense of completeness" and for the occasional meta-use?










share|improve this question




















  • 1





    What happens if T is already const?

    – Peter Wood
    May 8 '13 at 7:41






  • 1





    @PeterWood Works fine, at least in gcc 4.7.2

    – Angew
    May 8 '13 at 7:45






  • 3





    @PeterWood If it's already qualified, it gives the same type back, as required by the standard.

    – jrok
    May 8 '13 at 7:48






  • 2





    The reason for std::add_{l,r}value_reference is that void would error out on a naive T& or T&&, since you can't form a reference to void. As for add_const, I can only imagine symmetry.

    – Xeo
    May 8 '13 at 8:04






  • 1





    Concerning add_const, also see this Q&A

    – Andy Prowl
    May 8 '13 at 9:53
















23















Some type transformations in <type_traits> can also be expressed using core language syntax (e.g. std::add_const<T>::type is/seems equivalent to const T). Dtto for std::add_lvalue_reference, and perhaps others. What is the use for these type traits?



I fully understand the standard would be providing an "incomplete toolbox" without them, and I can imagine use in a meta way, something like this:



template<typename In, template <typename> class Modifier>
struct Apply {
typedef typename Modifier<T>::type Out;
};

Apply<int, std::add_const>


Are there any other use cases for these traits which can be expressed syntactically, or are they just included "out of a sense of completeness" and for the occasional meta-use?










share|improve this question




















  • 1





    What happens if T is already const?

    – Peter Wood
    May 8 '13 at 7:41






  • 1





    @PeterWood Works fine, at least in gcc 4.7.2

    – Angew
    May 8 '13 at 7:45






  • 3





    @PeterWood If it's already qualified, it gives the same type back, as required by the standard.

    – jrok
    May 8 '13 at 7:48






  • 2





    The reason for std::add_{l,r}value_reference is that void would error out on a naive T& or T&&, since you can't form a reference to void. As for add_const, I can only imagine symmetry.

    – Xeo
    May 8 '13 at 8:04






  • 1





    Concerning add_const, also see this Q&A

    – Andy Prowl
    May 8 '13 at 9:53














23












23








23


2






Some type transformations in <type_traits> can also be expressed using core language syntax (e.g. std::add_const<T>::type is/seems equivalent to const T). Dtto for std::add_lvalue_reference, and perhaps others. What is the use for these type traits?



I fully understand the standard would be providing an "incomplete toolbox" without them, and I can imagine use in a meta way, something like this:



template<typename In, template <typename> class Modifier>
struct Apply {
typedef typename Modifier<T>::type Out;
};

Apply<int, std::add_const>


Are there any other use cases for these traits which can be expressed syntactically, or are they just included "out of a sense of completeness" and for the occasional meta-use?










share|improve this question
















Some type transformations in <type_traits> can also be expressed using core language syntax (e.g. std::add_const<T>::type is/seems equivalent to const T). Dtto for std::add_lvalue_reference, and perhaps others. What is the use for these type traits?



I fully understand the standard would be providing an "incomplete toolbox" without them, and I can imagine use in a meta way, something like this:



template<typename In, template <typename> class Modifier>
struct Apply {
typedef typename Modifier<T>::type Out;
};

Apply<int, std::add_const>


Are there any other use cases for these traits which can be expressed syntactically, or are they just included "out of a sense of completeness" and for the occasional meta-use?







c++ c++11 language-lawyer






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 8 '13 at 7:44







Angew

















asked May 8 '13 at 7:37









AngewAngew

131k11249340




131k11249340








  • 1





    What happens if T is already const?

    – Peter Wood
    May 8 '13 at 7:41






  • 1





    @PeterWood Works fine, at least in gcc 4.7.2

    – Angew
    May 8 '13 at 7:45






  • 3





    @PeterWood If it's already qualified, it gives the same type back, as required by the standard.

    – jrok
    May 8 '13 at 7:48






  • 2





    The reason for std::add_{l,r}value_reference is that void would error out on a naive T& or T&&, since you can't form a reference to void. As for add_const, I can only imagine symmetry.

    – Xeo
    May 8 '13 at 8:04






  • 1





    Concerning add_const, also see this Q&A

    – Andy Prowl
    May 8 '13 at 9:53














  • 1





    What happens if T is already const?

    – Peter Wood
    May 8 '13 at 7:41






  • 1





    @PeterWood Works fine, at least in gcc 4.7.2

    – Angew
    May 8 '13 at 7:45






  • 3





    @PeterWood If it's already qualified, it gives the same type back, as required by the standard.

    – jrok
    May 8 '13 at 7:48






  • 2





    The reason for std::add_{l,r}value_reference is that void would error out on a naive T& or T&&, since you can't form a reference to void. As for add_const, I can only imagine symmetry.

    – Xeo
    May 8 '13 at 8:04






  • 1





    Concerning add_const, also see this Q&A

    – Andy Prowl
    May 8 '13 at 9:53








1




1





What happens if T is already const?

– Peter Wood
May 8 '13 at 7:41





What happens if T is already const?

– Peter Wood
May 8 '13 at 7:41




1




1





@PeterWood Works fine, at least in gcc 4.7.2

– Angew
May 8 '13 at 7:45





@PeterWood Works fine, at least in gcc 4.7.2

– Angew
May 8 '13 at 7:45




3




3





@PeterWood If it's already qualified, it gives the same type back, as required by the standard.

– jrok
May 8 '13 at 7:48





@PeterWood If it's already qualified, it gives the same type back, as required by the standard.

– jrok
May 8 '13 at 7:48




2




2





The reason for std::add_{l,r}value_reference is that void would error out on a naive T& or T&&, since you can't form a reference to void. As for add_const, I can only imagine symmetry.

– Xeo
May 8 '13 at 8:04





The reason for std::add_{l,r}value_reference is that void would error out on a naive T& or T&&, since you can't form a reference to void. As for add_const, I can only imagine symmetry.

– Xeo
May 8 '13 at 8:04




1




1





Concerning add_const, also see this Q&A

– Andy Prowl
May 8 '13 at 9:53





Concerning add_const, also see this Q&A

– Andy Prowl
May 8 '13 at 9:53












4 Answers
4






active

oldest

votes


















22














Those traits come from Boost and the proposal to add them to the standard, N1345, quotes Andrei Alexandrescu as saying:




"I understand the symmetry argument for adding add_const, add_volatile, add_cv, and add_pointer, however I would argue in favor of eliminating them. The language-provided equivalents are just simpler and nicer."




The same proposal also gives this rationale:




Author's Note: superficially the add_const, add_volatile and add_cv classes are irrelevant, since, for example, add_const::type is the same as T const, for all T (currently this does not apply to function types - but issue 295 addresses this). However the experience from boost is that several users have asked for these templates to be present in the library for the following reasons: (a) Some users find these more explicit - when combining transformation templates in particular, users like the kind of "built in documentation" that these templates provide. (b) Not all users are aware that cv-qualifying a reference is allowed and has no effect, or that cv-qualifying a type that is already cv-qualified is allowed and has no effect. (c) Compilers may emit warnings when cv-qualifying a type that is a reference, or already has a cv-qualifier, these templates can be implemented such that these messages are suppressed in these cases.




Also, for add_reference (renamed to add_lvalue_reference in the standard):




Author's Note: the add_reference template was one of the original motivations behind the boost type traits library. However the resolution to issue 106 makes the template appear largely redundant. In spite of that add_reference may well be useful in suppressing compiler warnings when inadvertently creating references to references in template code.







share|improve this answer



















  • 4





    add_{l,r}value_reference also plays nicely with void.

    – Xeo
    May 8 '13 at 8:07



















7














These traits are provided for occasional meta-use. It makes it possible to transport wanted cv-qualifiers around in meta programming.



template<class T,template<class> class Trait>
struct transform
{
/* working with T creating newT*/

typedef Trait<newT>::type type;
};

template<class T>
struct special_transform
: transfrom<T, std::add_const>
{};


In this case you could not replace std::add_const with const.






share|improve this answer
























  • In this case you wouldn't yeah, because you have especially crafted this to go side-by-side with the type traits. However, what if you passed const T in place of std::add_const removing the second template parameter all together? I believe it would work in this case.

    – Nik-Lz
    Oct 2 '18 at 5:49



















5














add_const can be used to resolve type deduction conflicts.



template <typename T>
class wrapper;

template <typename T>
bool operator==(wrapper<T> const& w, T const& t);


Problems arise if we use wrapper<T const>:



wrapper<int const> w = { 42 };
assert(w == 42); // Error: conflicting deduced types


T is simultaneously deduced to be both int and int const. This can be resolved using add_const:



template <typename T>
bool operator==(wrapper<T> const& w, add_const_t<T>& t);





share|improve this answer
























  • Interesting use case. Anything else that would make the second function parameter a non-deduced context would work too, but this one's quite concise.

    – Angew
    Feb 17 '17 at 8:13



















1














The only use case I know is illustrated below:



struct F
{
bool f() const { return true; }
bool f() { return false; }
};
assert(!F{}.f())
assert(std::add_const_t< F >{}.f());


It also needed for testing of cv-ref-qualified member-functions functionality, that may differs for different overloadings (only for lref-qualified modern C++ has handy std::as_const function):



struct F
{
int g() & { return 1; }
int g() const & { return 2; }
int g() && { return 3; }
int g() const && { return 4; }
};
F f;
assert(f.g() == 1);
assert(std::as_const(f).g() == 2);
assert(F{}.g() == 3);
assert(std::add_const_t< F >{}.g() == 4); // rarely needed, but if needed, then it helps





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%2f16435170%2fuse-cases-for-stdadd-const-and-similar%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    22














    Those traits come from Boost and the proposal to add them to the standard, N1345, quotes Andrei Alexandrescu as saying:




    "I understand the symmetry argument for adding add_const, add_volatile, add_cv, and add_pointer, however I would argue in favor of eliminating them. The language-provided equivalents are just simpler and nicer."




    The same proposal also gives this rationale:




    Author's Note: superficially the add_const, add_volatile and add_cv classes are irrelevant, since, for example, add_const::type is the same as T const, for all T (currently this does not apply to function types - but issue 295 addresses this). However the experience from boost is that several users have asked for these templates to be present in the library for the following reasons: (a) Some users find these more explicit - when combining transformation templates in particular, users like the kind of "built in documentation" that these templates provide. (b) Not all users are aware that cv-qualifying a reference is allowed and has no effect, or that cv-qualifying a type that is already cv-qualified is allowed and has no effect. (c) Compilers may emit warnings when cv-qualifying a type that is a reference, or already has a cv-qualifier, these templates can be implemented such that these messages are suppressed in these cases.




    Also, for add_reference (renamed to add_lvalue_reference in the standard):




    Author's Note: the add_reference template was one of the original motivations behind the boost type traits library. However the resolution to issue 106 makes the template appear largely redundant. In spite of that add_reference may well be useful in suppressing compiler warnings when inadvertently creating references to references in template code.







    share|improve this answer



















    • 4





      add_{l,r}value_reference also plays nicely with void.

      – Xeo
      May 8 '13 at 8:07
















    22














    Those traits come from Boost and the proposal to add them to the standard, N1345, quotes Andrei Alexandrescu as saying:




    "I understand the symmetry argument for adding add_const, add_volatile, add_cv, and add_pointer, however I would argue in favor of eliminating them. The language-provided equivalents are just simpler and nicer."




    The same proposal also gives this rationale:




    Author's Note: superficially the add_const, add_volatile and add_cv classes are irrelevant, since, for example, add_const::type is the same as T const, for all T (currently this does not apply to function types - but issue 295 addresses this). However the experience from boost is that several users have asked for these templates to be present in the library for the following reasons: (a) Some users find these more explicit - when combining transformation templates in particular, users like the kind of "built in documentation" that these templates provide. (b) Not all users are aware that cv-qualifying a reference is allowed and has no effect, or that cv-qualifying a type that is already cv-qualified is allowed and has no effect. (c) Compilers may emit warnings when cv-qualifying a type that is a reference, or already has a cv-qualifier, these templates can be implemented such that these messages are suppressed in these cases.




    Also, for add_reference (renamed to add_lvalue_reference in the standard):




    Author's Note: the add_reference template was one of the original motivations behind the boost type traits library. However the resolution to issue 106 makes the template appear largely redundant. In spite of that add_reference may well be useful in suppressing compiler warnings when inadvertently creating references to references in template code.







    share|improve this answer



















    • 4





      add_{l,r}value_reference also plays nicely with void.

      – Xeo
      May 8 '13 at 8:07














    22












    22








    22







    Those traits come from Boost and the proposal to add them to the standard, N1345, quotes Andrei Alexandrescu as saying:




    "I understand the symmetry argument for adding add_const, add_volatile, add_cv, and add_pointer, however I would argue in favor of eliminating them. The language-provided equivalents are just simpler and nicer."




    The same proposal also gives this rationale:




    Author's Note: superficially the add_const, add_volatile and add_cv classes are irrelevant, since, for example, add_const::type is the same as T const, for all T (currently this does not apply to function types - but issue 295 addresses this). However the experience from boost is that several users have asked for these templates to be present in the library for the following reasons: (a) Some users find these more explicit - when combining transformation templates in particular, users like the kind of "built in documentation" that these templates provide. (b) Not all users are aware that cv-qualifying a reference is allowed and has no effect, or that cv-qualifying a type that is already cv-qualified is allowed and has no effect. (c) Compilers may emit warnings when cv-qualifying a type that is a reference, or already has a cv-qualifier, these templates can be implemented such that these messages are suppressed in these cases.




    Also, for add_reference (renamed to add_lvalue_reference in the standard):




    Author's Note: the add_reference template was one of the original motivations behind the boost type traits library. However the resolution to issue 106 makes the template appear largely redundant. In spite of that add_reference may well be useful in suppressing compiler warnings when inadvertently creating references to references in template code.







    share|improve this answer













    Those traits come from Boost and the proposal to add them to the standard, N1345, quotes Andrei Alexandrescu as saying:




    "I understand the symmetry argument for adding add_const, add_volatile, add_cv, and add_pointer, however I would argue in favor of eliminating them. The language-provided equivalents are just simpler and nicer."




    The same proposal also gives this rationale:




    Author's Note: superficially the add_const, add_volatile and add_cv classes are irrelevant, since, for example, add_const::type is the same as T const, for all T (currently this does not apply to function types - but issue 295 addresses this). However the experience from boost is that several users have asked for these templates to be present in the library for the following reasons: (a) Some users find these more explicit - when combining transformation templates in particular, users like the kind of "built in documentation" that these templates provide. (b) Not all users are aware that cv-qualifying a reference is allowed and has no effect, or that cv-qualifying a type that is already cv-qualified is allowed and has no effect. (c) Compilers may emit warnings when cv-qualifying a type that is a reference, or already has a cv-qualifier, these templates can be implemented such that these messages are suppressed in these cases.




    Also, for add_reference (renamed to add_lvalue_reference in the standard):




    Author's Note: the add_reference template was one of the original motivations behind the boost type traits library. However the resolution to issue 106 makes the template appear largely redundant. In spite of that add_reference may well be useful in suppressing compiler warnings when inadvertently creating references to references in template code.








    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered May 8 '13 at 8:03









    Jonathan WakelyJonathan Wakely

    130k16239402




    130k16239402








    • 4





      add_{l,r}value_reference also plays nicely with void.

      – Xeo
      May 8 '13 at 8:07














    • 4





      add_{l,r}value_reference also plays nicely with void.

      – Xeo
      May 8 '13 at 8:07








    4




    4





    add_{l,r}value_reference also plays nicely with void.

    – Xeo
    May 8 '13 at 8:07





    add_{l,r}value_reference also plays nicely with void.

    – Xeo
    May 8 '13 at 8:07













    7














    These traits are provided for occasional meta-use. It makes it possible to transport wanted cv-qualifiers around in meta programming.



    template<class T,template<class> class Trait>
    struct transform
    {
    /* working with T creating newT*/

    typedef Trait<newT>::type type;
    };

    template<class T>
    struct special_transform
    : transfrom<T, std::add_const>
    {};


    In this case you could not replace std::add_const with const.






    share|improve this answer
























    • In this case you wouldn't yeah, because you have especially crafted this to go side-by-side with the type traits. However, what if you passed const T in place of std::add_const removing the second template parameter all together? I believe it would work in this case.

      – Nik-Lz
      Oct 2 '18 at 5:49
















    7














    These traits are provided for occasional meta-use. It makes it possible to transport wanted cv-qualifiers around in meta programming.



    template<class T,template<class> class Trait>
    struct transform
    {
    /* working with T creating newT*/

    typedef Trait<newT>::type type;
    };

    template<class T>
    struct special_transform
    : transfrom<T, std::add_const>
    {};


    In this case you could not replace std::add_const with const.






    share|improve this answer
























    • In this case you wouldn't yeah, because you have especially crafted this to go side-by-side with the type traits. However, what if you passed const T in place of std::add_const removing the second template parameter all together? I believe it would work in this case.

      – Nik-Lz
      Oct 2 '18 at 5:49














    7












    7








    7







    These traits are provided for occasional meta-use. It makes it possible to transport wanted cv-qualifiers around in meta programming.



    template<class T,template<class> class Trait>
    struct transform
    {
    /* working with T creating newT*/

    typedef Trait<newT>::type type;
    };

    template<class T>
    struct special_transform
    : transfrom<T, std::add_const>
    {};


    In this case you could not replace std::add_const with const.






    share|improve this answer













    These traits are provided for occasional meta-use. It makes it possible to transport wanted cv-qualifiers around in meta programming.



    template<class T,template<class> class Trait>
    struct transform
    {
    /* working with T creating newT*/

    typedef Trait<newT>::type type;
    };

    template<class T>
    struct special_transform
    : transfrom<T, std::add_const>
    {};


    In this case you could not replace std::add_const with const.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jun 4 '13 at 6:22









    Jan HerrmannJan Herrmann

    2,2091017




    2,2091017













    • In this case you wouldn't yeah, because you have especially crafted this to go side-by-side with the type traits. However, what if you passed const T in place of std::add_const removing the second template parameter all together? I believe it would work in this case.

      – Nik-Lz
      Oct 2 '18 at 5:49



















    • In this case you wouldn't yeah, because you have especially crafted this to go side-by-side with the type traits. However, what if you passed const T in place of std::add_const removing the second template parameter all together? I believe it would work in this case.

      – Nik-Lz
      Oct 2 '18 at 5:49

















    In this case you wouldn't yeah, because you have especially crafted this to go side-by-side with the type traits. However, what if you passed const T in place of std::add_const removing the second template parameter all together? I believe it would work in this case.

    – Nik-Lz
    Oct 2 '18 at 5:49





    In this case you wouldn't yeah, because you have especially crafted this to go side-by-side with the type traits. However, what if you passed const T in place of std::add_const removing the second template parameter all together? I believe it would work in this case.

    – Nik-Lz
    Oct 2 '18 at 5:49











    5














    add_const can be used to resolve type deduction conflicts.



    template <typename T>
    class wrapper;

    template <typename T>
    bool operator==(wrapper<T> const& w, T const& t);


    Problems arise if we use wrapper<T const>:



    wrapper<int const> w = { 42 };
    assert(w == 42); // Error: conflicting deduced types


    T is simultaneously deduced to be both int and int const. This can be resolved using add_const:



    template <typename T>
    bool operator==(wrapper<T> const& w, add_const_t<T>& t);





    share|improve this answer
























    • Interesting use case. Anything else that would make the second function parameter a non-deduced context would work too, but this one's quite concise.

      – Angew
      Feb 17 '17 at 8:13
















    5














    add_const can be used to resolve type deduction conflicts.



    template <typename T>
    class wrapper;

    template <typename T>
    bool operator==(wrapper<T> const& w, T const& t);


    Problems arise if we use wrapper<T const>:



    wrapper<int const> w = { 42 };
    assert(w == 42); // Error: conflicting deduced types


    T is simultaneously deduced to be both int and int const. This can be resolved using add_const:



    template <typename T>
    bool operator==(wrapper<T> const& w, add_const_t<T>& t);





    share|improve this answer
























    • Interesting use case. Anything else that would make the second function parameter a non-deduced context would work too, but this one's quite concise.

      – Angew
      Feb 17 '17 at 8:13














    5












    5








    5







    add_const can be used to resolve type deduction conflicts.



    template <typename T>
    class wrapper;

    template <typename T>
    bool operator==(wrapper<T> const& w, T const& t);


    Problems arise if we use wrapper<T const>:



    wrapper<int const> w = { 42 };
    assert(w == 42); // Error: conflicting deduced types


    T is simultaneously deduced to be both int and int const. This can be resolved using add_const:



    template <typename T>
    bool operator==(wrapper<T> const& w, add_const_t<T>& t);





    share|improve this answer













    add_const can be used to resolve type deduction conflicts.



    template <typename T>
    class wrapper;

    template <typename T>
    bool operator==(wrapper<T> const& w, T const& t);


    Problems arise if we use wrapper<T const>:



    wrapper<int const> w = { 42 };
    assert(w == 42); // Error: conflicting deduced types


    T is simultaneously deduced to be both int and int const. This can be resolved using add_const:



    template <typename T>
    bool operator==(wrapper<T> const& w, add_const_t<T>& t);






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Feb 17 '17 at 1:28









    Joseph ThomsonJoseph Thomson

    5,0561731




    5,0561731













    • Interesting use case. Anything else that would make the second function parameter a non-deduced context would work too, but this one's quite concise.

      – Angew
      Feb 17 '17 at 8:13



















    • Interesting use case. Anything else that would make the second function parameter a non-deduced context would work too, but this one's quite concise.

      – Angew
      Feb 17 '17 at 8:13

















    Interesting use case. Anything else that would make the second function parameter a non-deduced context would work too, but this one's quite concise.

    – Angew
    Feb 17 '17 at 8:13





    Interesting use case. Anything else that would make the second function parameter a non-deduced context would work too, but this one's quite concise.

    – Angew
    Feb 17 '17 at 8:13











    1














    The only use case I know is illustrated below:



    struct F
    {
    bool f() const { return true; }
    bool f() { return false; }
    };
    assert(!F{}.f())
    assert(std::add_const_t< F >{}.f());


    It also needed for testing of cv-ref-qualified member-functions functionality, that may differs for different overloadings (only for lref-qualified modern C++ has handy std::as_const function):



    struct F
    {
    int g() & { return 1; }
    int g() const & { return 2; }
    int g() && { return 3; }
    int g() const && { return 4; }
    };
    F f;
    assert(f.g() == 1);
    assert(std::as_const(f).g() == 2);
    assert(F{}.g() == 3);
    assert(std::add_const_t< F >{}.g() == 4); // rarely needed, but if needed, then it helps





    share|improve this answer




























      1














      The only use case I know is illustrated below:



      struct F
      {
      bool f() const { return true; }
      bool f() { return false; }
      };
      assert(!F{}.f())
      assert(std::add_const_t< F >{}.f());


      It also needed for testing of cv-ref-qualified member-functions functionality, that may differs for different overloadings (only for lref-qualified modern C++ has handy std::as_const function):



      struct F
      {
      int g() & { return 1; }
      int g() const & { return 2; }
      int g() && { return 3; }
      int g() const && { return 4; }
      };
      F f;
      assert(f.g() == 1);
      assert(std::as_const(f).g() == 2);
      assert(F{}.g() == 3);
      assert(std::add_const_t< F >{}.g() == 4); // rarely needed, but if needed, then it helps





      share|improve this answer


























        1












        1








        1







        The only use case I know is illustrated below:



        struct F
        {
        bool f() const { return true; }
        bool f() { return false; }
        };
        assert(!F{}.f())
        assert(std::add_const_t< F >{}.f());


        It also needed for testing of cv-ref-qualified member-functions functionality, that may differs for different overloadings (only for lref-qualified modern C++ has handy std::as_const function):



        struct F
        {
        int g() & { return 1; }
        int g() const & { return 2; }
        int g() && { return 3; }
        int g() const && { return 4; }
        };
        F f;
        assert(f.g() == 1);
        assert(std::as_const(f).g() == 2);
        assert(F{}.g() == 3);
        assert(std::add_const_t< F >{}.g() == 4); // rarely needed, but if needed, then it helps





        share|improve this answer













        The only use case I know is illustrated below:



        struct F
        {
        bool f() const { return true; }
        bool f() { return false; }
        };
        assert(!F{}.f())
        assert(std::add_const_t< F >{}.f());


        It also needed for testing of cv-ref-qualified member-functions functionality, that may differs for different overloadings (only for lref-qualified modern C++ has handy std::as_const function):



        struct F
        {
        int g() & { return 1; }
        int g() const & { return 2; }
        int g() && { return 3; }
        int g() const && { return 4; }
        };
        F f;
        assert(f.g() == 1);
        assert(std::as_const(f).g() == 2);
        assert(F{}.g() == 3);
        assert(std::add_const_t< F >{}.g() == 4); // rarely needed, but if needed, then it helps






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Feb 21 '16 at 21:14









        OrientOrient

        6,21753295




        6,21753295






























            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%2f16435170%2fuse-cases-for-stdadd-const-and-similar%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

            A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

            Calculate evaluation metrics using cross_val_predict sklearn

            Insert data from modal to MySQL (multiple modal on website)