# add_const or remove_const based on another type

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::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-const\n"; }
void m() const { std::cout << "Const\n"; }
};

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?

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 like constness_from<foo>::to<bar>. There's a lot of valid option. A strawpoll might be nice :p – Calak Nov 21 '18 at 19:23
• copy_const sounds like "copy constructor"... – einpoklum Nov 21 '18 at 21:58
• @Calak: See my answer. – einpoklum Nov 21 '18 at 22:13

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