Use cases for std::add_const and similar
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
|
show 3 more comments
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
1
What happens ifT
is alreadyconst
?
– 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 forstd::add_{l,r}value_reference
is thatvoid
would error out on a naiveT&
orT&&
, since you can't form a reference tovoid
. As foradd_const
, I can only imagine symmetry.
– Xeo
May 8 '13 at 8:04
1
Concerningadd_const
, also see this Q&A
– Andy Prowl
May 8 '13 at 9:53
|
show 3 more comments
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
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
c++ c++11 language-lawyer
edited May 8 '13 at 7:44
Angew
asked May 8 '13 at 7:37
AngewAngew
131k11249340
131k11249340
1
What happens ifT
is alreadyconst
?
– 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 forstd::add_{l,r}value_reference
is thatvoid
would error out on a naiveT&
orT&&
, since you can't form a reference tovoid
. As foradd_const
, I can only imagine symmetry.
– Xeo
May 8 '13 at 8:04
1
Concerningadd_const
, also see this Q&A
– Andy Prowl
May 8 '13 at 9:53
|
show 3 more comments
1
What happens ifT
is alreadyconst
?
– 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 forstd::add_{l,r}value_reference
is thatvoid
would error out on a naiveT&
orT&&
, since you can't form a reference tovoid
. As foradd_const
, I can only imagine symmetry.
– Xeo
May 8 '13 at 8:04
1
Concerningadd_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
|
show 3 more comments
4 Answers
4
active
oldest
votes
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
, andadd_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.
4
add_{l,r}value_reference
also plays nicely withvoid
.
– Xeo
May 8 '13 at 8:07
add a comment |
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
.
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 passedconst T
in place ofstd::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
add a comment |
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);
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
add a comment |
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
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%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
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
, andadd_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.
4
add_{l,r}value_reference
also plays nicely withvoid
.
– Xeo
May 8 '13 at 8:07
add a comment |
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
, andadd_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.
4
add_{l,r}value_reference
also plays nicely withvoid
.
– Xeo
May 8 '13 at 8:07
add a comment |
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
, andadd_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.
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
, andadd_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.
answered May 8 '13 at 8:03
Jonathan WakelyJonathan Wakely
130k16239402
130k16239402
4
add_{l,r}value_reference
also plays nicely withvoid
.
– Xeo
May 8 '13 at 8:07
add a comment |
4
add_{l,r}value_reference
also plays nicely withvoid
.
– 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
add a comment |
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
.
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 passedconst T
in place ofstd::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
add a comment |
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
.
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 passedconst T
in place ofstd::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
add a comment |
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
.
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
.
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 passedconst T
in place ofstd::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
add a comment |
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 passedconst T
in place ofstd::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
add a comment |
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);
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
add a comment |
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);
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
add a comment |
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);
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);
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
add a comment |
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
add a comment |
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
add a comment |
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
add a comment |
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
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
answered Feb 21 '16 at 21:14
OrientOrient
6,21753295
6,21753295
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%2f16435170%2fuse-cases-for-stdadd-const-and-similar%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
1
What happens if
T
is alreadyconst
?– 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 thatvoid
would error out on a naiveT&
orT&&
, since you can't form a reference tovoid
. As foradd_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