add_const or remove_const based on another type
up vote
5
down vote
favorite
Here is a type trait which - I feel - could fit in std
next to std::add_const
and std::remove_const
:
#include <type_traits>
template <typename T>
struct set_constness_of {
template <typename U>
struct by {
using type = typename std::conditional<
std::is_const<U>::value,
typename std::add_const<T>::type,
typename std::remove_const<T>::type
>::type;
};
};
Note this is intentionally C++11 to minimize requirements for using it. One can obviously define set_constness_of_t
in which by
is a type rather than a struct with a type.
I've also written a tiny sample program (coliru.com) to ensure it runs, at least for some cases.
/* the above definition of set_constness_of goes here (paste it) */
#inlcude <iostream>
struct foo {
void m() { std::cout << "Non-constn"; }
void m() const { std::cout << "Constn"; }
};
template <class T> void call_m() { T().m(); }
int main() {
call_m<foo>();
using bar = const int;
call_m< set_constness_of<foo>::by<bar>::type >();
}
Questions:
- Is this correctly defined for all cases?
- What do you think about placing the second template parameter as an inner struct's template param, rather than having two template parameters on the outer struct?
- What do you think about the choice of naming?
Other comments are welcome.
c++ template type-safety casting constants
add a comment |
up vote
5
down vote
favorite
Here is a type trait which - I feel - could fit in std
next to std::add_const
and std::remove_const
:
#include <type_traits>
template <typename T>
struct set_constness_of {
template <typename U>
struct by {
using type = typename std::conditional<
std::is_const<U>::value,
typename std::add_const<T>::type,
typename std::remove_const<T>::type
>::type;
};
};
Note this is intentionally C++11 to minimize requirements for using it. One can obviously define set_constness_of_t
in which by
is a type rather than a struct with a type.
I've also written a tiny sample program (coliru.com) to ensure it runs, at least for some cases.
/* the above definition of set_constness_of goes here (paste it) */
#inlcude <iostream>
struct foo {
void m() { std::cout << "Non-constn"; }
void m() const { std::cout << "Constn"; }
};
template <class T> void call_m() { T().m(); }
int main() {
call_m<foo>();
using bar = const int;
call_m< set_constness_of<foo>::by<bar>::type >();
}
Questions:
- Is this correctly defined for all cases?
- What do you think about placing the second template parameter as an inner struct's template param, rather than having two template parameters on the outer struct?
- What do you think about the choice of naming?
Other comments are welcome.
c++ template type-safety casting constants
add a comment |
up vote
5
down vote
favorite
up vote
5
down vote
favorite
Here is a type trait which - I feel - could fit in std
next to std::add_const
and std::remove_const
:
#include <type_traits>
template <typename T>
struct set_constness_of {
template <typename U>
struct by {
using type = typename std::conditional<
std::is_const<U>::value,
typename std::add_const<T>::type,
typename std::remove_const<T>::type
>::type;
};
};
Note this is intentionally C++11 to minimize requirements for using it. One can obviously define set_constness_of_t
in which by
is a type rather than a struct with a type.
I've also written a tiny sample program (coliru.com) to ensure it runs, at least for some cases.
/* the above definition of set_constness_of goes here (paste it) */
#inlcude <iostream>
struct foo {
void m() { std::cout << "Non-constn"; }
void m() const { std::cout << "Constn"; }
};
template <class T> void call_m() { T().m(); }
int main() {
call_m<foo>();
using bar = const int;
call_m< set_constness_of<foo>::by<bar>::type >();
}
Questions:
- Is this correctly defined for all cases?
- What do you think about placing the second template parameter as an inner struct's template param, rather than having two template parameters on the outer struct?
- What do you think about the choice of naming?
Other comments are welcome.
c++ template type-safety casting constants
Here is a type trait which - I feel - could fit in std
next to std::add_const
and std::remove_const
:
#include <type_traits>
template <typename T>
struct set_constness_of {
template <typename U>
struct by {
using type = typename std::conditional<
std::is_const<U>::value,
typename std::add_const<T>::type,
typename std::remove_const<T>::type
>::type;
};
};
Note this is intentionally C++11 to minimize requirements for using it. One can obviously define set_constness_of_t
in which by
is a type rather than a struct with a type.
I've also written a tiny sample program (coliru.com) to ensure it runs, at least for some cases.
/* the above definition of set_constness_of goes here (paste it) */
#inlcude <iostream>
struct foo {
void m() { std::cout << "Non-constn"; }
void m() const { std::cout << "Constn"; }
};
template <class T> void call_m() { T().m(); }
int main() {
call_m<foo>();
using bar = const int;
call_m< set_constness_of<foo>::by<bar>::type >();
}
Questions:
- Is this correctly defined for all cases?
- What do you think about placing the second template parameter as an inner struct's template param, rather than having two template parameters on the outer struct?
- What do you think about the choice of naming?
Other comments are welcome.
c++ template type-safety casting constants
c++ template type-safety casting constants
edited 9 hours ago
asked 21 hours ago
einpoklum
1,096417
1,096417
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
3
down vote
I don't see any obvious omissions or bugs.
The naming and inner struct are neatly expressive (and remind me of some testing frameworks' precondition/assertion chaining). It's not something that's done by the standard library, but I don't think it should be hugely controversial.
I might go with a naming like copy_const<foo>::from<bar>
- or perhaps even the other way around: copy_const<bar>::to<foo>
. Or even both! (Actually, I now wish std::is_assignable
worked like that - it would be easier to remember which parameter is which!)
None of the above is a concrete suggestion - intended merely as food for thought!
If find the second version very fluent! Or maybe something likeconstness_from<foo>::to<bar>
. There's a lot of valid option. A strawpoll might be nice :p
– Calak
12 hours ago
copy_const
sounds like "copy constructor"...
– einpoklum
9 hours ago
@Calak: See my answer.
– einpoklum
9 hours ago
add a comment |
up vote
2
down vote
Following @Calak's comment, I'm now thinking of the following change of order of the template parameters:
#include <type_traits>
template <typename U>
struct constness_of {
enum { value = std::is_const<U>::value };
template <typename T>
struct applied_to {
using type = typename std::conditional<
value,
typename std::add_const<T>::type,
typename std::remove_const<T>::type
>::type;
};
#if __cplusplus >= 201402L
template <typename U>
using applied_to_t = typename applied_to<U>::type;
#endif
};
Which would be used as follows:
if (constness_of<bar>::value) { std::cout << "bar is const!n"; }
and:
using altered_foo = constness_of<bar>::applied_to<foo>::type;
using altered_foo_2 = constness_of<bar>::applied_to_t<foo>;
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
I don't see any obvious omissions or bugs.
The naming and inner struct are neatly expressive (and remind me of some testing frameworks' precondition/assertion chaining). It's not something that's done by the standard library, but I don't think it should be hugely controversial.
I might go with a naming like copy_const<foo>::from<bar>
- or perhaps even the other way around: copy_const<bar>::to<foo>
. Or even both! (Actually, I now wish std::is_assignable
worked like that - it would be easier to remember which parameter is which!)
None of the above is a concrete suggestion - intended merely as food for thought!
If find the second version very fluent! Or maybe something likeconstness_from<foo>::to<bar>
. There's a lot of valid option. A strawpoll might be nice :p
– Calak
12 hours ago
copy_const
sounds like "copy constructor"...
– einpoklum
9 hours ago
@Calak: See my answer.
– einpoklum
9 hours ago
add a comment |
up vote
3
down vote
I don't see any obvious omissions or bugs.
The naming and inner struct are neatly expressive (and remind me of some testing frameworks' precondition/assertion chaining). It's not something that's done by the standard library, but I don't think it should be hugely controversial.
I might go with a naming like copy_const<foo>::from<bar>
- or perhaps even the other way around: copy_const<bar>::to<foo>
. Or even both! (Actually, I now wish std::is_assignable
worked like that - it would be easier to remember which parameter is which!)
None of the above is a concrete suggestion - intended merely as food for thought!
If find the second version very fluent! Or maybe something likeconstness_from<foo>::to<bar>
. There's a lot of valid option. A strawpoll might be nice :p
– Calak
12 hours ago
copy_const
sounds like "copy constructor"...
– einpoklum
9 hours ago
@Calak: See my answer.
– einpoklum
9 hours ago
add a comment |
up vote
3
down vote
up vote
3
down vote
I don't see any obvious omissions or bugs.
The naming and inner struct are neatly expressive (and remind me of some testing frameworks' precondition/assertion chaining). It's not something that's done by the standard library, but I don't think it should be hugely controversial.
I might go with a naming like copy_const<foo>::from<bar>
- or perhaps even the other way around: copy_const<bar>::to<foo>
. Or even both! (Actually, I now wish std::is_assignable
worked like that - it would be easier to remember which parameter is which!)
None of the above is a concrete suggestion - intended merely as food for thought!
I don't see any obvious omissions or bugs.
The naming and inner struct are neatly expressive (and remind me of some testing frameworks' precondition/assertion chaining). It's not something that's done by the standard library, but I don't think it should be hugely controversial.
I might go with a naming like copy_const<foo>::from<bar>
- or perhaps even the other way around: copy_const<bar>::to<foo>
. Or even both! (Actually, I now wish std::is_assignable
worked like that - it would be easier to remember which parameter is which!)
None of the above is a concrete suggestion - intended merely as food for thought!
edited 12 hours ago
answered 12 hours ago
Toby Speight
22.2k536109
22.2k536109
If find the second version very fluent! Or maybe something likeconstness_from<foo>::to<bar>
. There's a lot of valid option. A strawpoll might be nice :p
– Calak
12 hours ago
copy_const
sounds like "copy constructor"...
– einpoklum
9 hours ago
@Calak: See my answer.
– einpoklum
9 hours ago
add a comment |
If find the second version very fluent! Or maybe something likeconstness_from<foo>::to<bar>
. There's a lot of valid option. A strawpoll might be nice :p
– Calak
12 hours ago
copy_const
sounds like "copy constructor"...
– einpoklum
9 hours ago
@Calak: See my answer.
– einpoklum
9 hours ago
If find the second version very fluent! Or maybe something like
constness_from<foo>::to<bar>
. There's a lot of valid option. A strawpoll might be nice :p– Calak
12 hours ago
If find the second version very fluent! Or maybe something like
constness_from<foo>::to<bar>
. There's a lot of valid option. A strawpoll might be nice :p– Calak
12 hours ago
copy_const
sounds like "copy constructor"...– einpoklum
9 hours ago
copy_const
sounds like "copy constructor"...– einpoklum
9 hours ago
@Calak: See my answer.
– einpoklum
9 hours ago
@Calak: See my answer.
– einpoklum
9 hours ago
add a comment |
up vote
2
down vote
Following @Calak's comment, I'm now thinking of the following change of order of the template parameters:
#include <type_traits>
template <typename U>
struct constness_of {
enum { value = std::is_const<U>::value };
template <typename T>
struct applied_to {
using type = typename std::conditional<
value,
typename std::add_const<T>::type,
typename std::remove_const<T>::type
>::type;
};
#if __cplusplus >= 201402L
template <typename U>
using applied_to_t = typename applied_to<U>::type;
#endif
};
Which would be used as follows:
if (constness_of<bar>::value) { std::cout << "bar is const!n"; }
and:
using altered_foo = constness_of<bar>::applied_to<foo>::type;
using altered_foo_2 = constness_of<bar>::applied_to_t<foo>;
add a comment |
up vote
2
down vote
Following @Calak's comment, I'm now thinking of the following change of order of the template parameters:
#include <type_traits>
template <typename U>
struct constness_of {
enum { value = std::is_const<U>::value };
template <typename T>
struct applied_to {
using type = typename std::conditional<
value,
typename std::add_const<T>::type,
typename std::remove_const<T>::type
>::type;
};
#if __cplusplus >= 201402L
template <typename U>
using applied_to_t = typename applied_to<U>::type;
#endif
};
Which would be used as follows:
if (constness_of<bar>::value) { std::cout << "bar is const!n"; }
and:
using altered_foo = constness_of<bar>::applied_to<foo>::type;
using altered_foo_2 = constness_of<bar>::applied_to_t<foo>;
add a comment |
up vote
2
down vote
up vote
2
down vote
Following @Calak's comment, I'm now thinking of the following change of order of the template parameters:
#include <type_traits>
template <typename U>
struct constness_of {
enum { value = std::is_const<U>::value };
template <typename T>
struct applied_to {
using type = typename std::conditional<
value,
typename std::add_const<T>::type,
typename std::remove_const<T>::type
>::type;
};
#if __cplusplus >= 201402L
template <typename U>
using applied_to_t = typename applied_to<U>::type;
#endif
};
Which would be used as follows:
if (constness_of<bar>::value) { std::cout << "bar is const!n"; }
and:
using altered_foo = constness_of<bar>::applied_to<foo>::type;
using altered_foo_2 = constness_of<bar>::applied_to_t<foo>;
Following @Calak's comment, I'm now thinking of the following change of order of the template parameters:
#include <type_traits>
template <typename U>
struct constness_of {
enum { value = std::is_const<U>::value };
template <typename T>
struct applied_to {
using type = typename std::conditional<
value,
typename std::add_const<T>::type,
typename std::remove_const<T>::type
>::type;
};
#if __cplusplus >= 201402L
template <typename U>
using applied_to_t = typename applied_to<U>::type;
#endif
};
Which would be used as follows:
if (constness_of<bar>::value) { std::cout << "bar is const!n"; }
and:
using altered_foo = constness_of<bar>::applied_to<foo>::type;
using altered_foo_2 = constness_of<bar>::applied_to_t<foo>;
answered 9 hours ago
einpoklum
1,096417
1,096417
add a comment |
add a comment |
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%2fcodereview.stackexchange.com%2fquestions%2f208121%2fadd-const-or-remove-const-based-on-another-type%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