[type traits] add a set of templates to propagate const etc from one type to another?

Hello, I've been looking at the Type Traits library recently, and it looks wonderful overall. However, it's lacking a use case that I end up needing quite often, so I thought I'd suggest it in case the authors and/or other users of the library find it useful. Allow me to explain. So Type Traits has the add_const / remove_const / is_const triplet (and similar for a few other type properties). add_const is great when you always know that you want to add the const, but sometimes you only want to do it conditionally to another type being const. So recently I've ended up using something like this from quite a few places in my code: template<class Source, class Target> struct propagate_const { typedef Target type; }; template<class Source, class Target> struct propagate_const<const Source, Target> { typedef const Target type; }; That is, propagate_const<Source, Target> will only add const to Target if Source is const too. What are the use cases for this? Well, for example recently I was writing an iterator class, and I wanted to avoid duplicating the code for the const_iterator case. Not a big deal, as it turned out, as I could just pass a const type as the template argument and have it behave as the const iterator. The only problem was that I was doing some pointer arithmetic with reinterpret_casts from T* to char* and back (where T is the template argument), so the compiler would complain if T was const. So instead of char I defined this: typedef typename propagate_const<T, char>::type char_type; Of course I could also have done this with a combination of is_const and add_const, but this would probably require more code than the propagate_const definition above. So what do people think? Would it be a useful addition alongside add_* and remove_*? Thanks, Vasilis P.S. Please CC me in your replies, as I've set the mailing lists to not send me emails (similar to not being subscribed). -- Vasilis Vasaitis "A man is well or woe as he thinks himself so."

Vasilis Vasaitis wrote: [snip]
That is, propagate_const<Source, Target> will only add const to Target if Source is const too.
[snip] For the Numeric_Bindings library (under development) we're using an identical mechanism called copy_const. I would welcome such an addition to the type traits library. Cheers, RUtger

On Tue, Mar 2, 2010 at 11:42 AM, Rutger ter Borg <rutger@terborg.net> wrote:
Vasilis Vasaitis wrote:
[snip]
That is, propagate_const<Source, Target> will only add const to Target if Source is const too.
[snip]
For the Numeric_Bindings library (under development) we're using an identical mechanism called copy_const. I would welcome such an addition to the type traits library.
I too have needed and created propogate const (actually propogate const and/or volatile). I'd definitely appreciate such an addition to Boost.TypeTraits. -- -Matt Calabrese

For the Numeric_Bindings library (under development) we're using an identical mechanism called copy_const. I would welcome such an addition to the type traits library.
I too have needed and created propogate const (actually propogate const and/or volatile). I'd definitely appreciate such an addition to Boost.TypeTraits.
My gut feeling would be to call this "copy_cv" and it would do what it's name suggests, take a type and make it's cv-qualifiers the same as some other type. Would someone please file a feature request on the Trac for this so it doesn't get lost? Thanks, John.

John Maddock wrote:
My gut feeling would be to call this "copy_cv" and it would do what it's name suggests, take a type and make it's cv-qualifiers the same as some other type. Would someone please file a feature request on the Trac for this so it doesn't get lost?
Thanks, John.
Ticket added at https://svn.boost.org/trac/boost/ticket/3970 Cheers, Rutger

John Maddock wrote:
I too have needed and created propogate const (actually propogate const and/or volatile). I'd definitely appreciate such an addition to Boost.TypeTraits.
My gut feeling would be to call this "copy_cv" and it would do what it's name suggests, take a type and make it's cv-qualifiers the same as some other type.
Nice name. The "cv" part is right on target, and "copy" is short and clear. If one wants only const or volatile, one need only combine copy_cv with remove_volatile or remove_const, so copy_const and copy_volatile are not required. However, since there is remove_const, remove_cv, and remove_volatile, wouldn't it be less surprising to add copy_const, copy_cv, and copy_volatile? _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Stewart, Robert wrote:
John Maddock wrote:
I too have needed and created propogate const (actually propogate const and/or volatile). I'd definitely appreciate such an addition to Boost.TypeTraits. My gut feeling would be to call this "copy_cv" and it would do what it's name suggests, take a type and make it's cv-qualifiers the same as some other type.
Nice name. The "cv" part is right on target, and "copy" is short and clear.
If one wants only const or volatile, one need only combine copy_cv with remove_volatile or remove_const, so copy_const and copy_volatile are not required. However, since there is remove_const, remove_cv, and remove_volatile, wouldn't it be less surprising to add copy_const, copy_cv, and copy_volatile?
This depends on how you define copy_const. I've used it where it simply adds (and never removes) const and volatile qualifiers on the "To" type, so remove_volatile< copy_cv< From, To >::type >::type isn't the same as copy_const< From, To >::type when To is volatile-qualified. Also, I, too, use an implementation called "propagate_const" and "propagate_cv". To me, "propagate" seems to better evoke the pure addition of qualifiers, whereas "copy" *could* (to some people) mean the overwriting of qualifiers (at least more so than "propagate"): propagate_const< int, const float >::type -> const float copy_const< int, const float >::type -> float (???) - Jeff

Jeffrey Hellrung wrote"
Stewart, Robert wrote:
John Maddock wrote:
I too have needed and created propogate const (actually propogate const and/or volatile). I'd definitely appreciate such an addition to Boost.TypeTraits. My gut feeling would be to call this "copy_cv" and it would do what it's name suggests, take a type and make it's cv-qualifiers the same as some other type.
Nice name. The "cv" part is right on target, and "copy" is short and clear.
If one wants only const or volatile, one need only combine copy_cv with remove_volatile or remove_const, so copy_const and copy_volatile are not required. However, since there is remove_const, remove_cv, and remove_volatile, wouldn't it be less surprising to add copy_const, copy_cv, and copy_volatile?
This depends on how you define copy_const. I've used it where it simply adds (and never removes) const and volatile qualifiers on the "To" type, so remove_volatile< copy_cv< From, To >::type >::type isn't the same as copy_const< From, To >::type when To is volatile-qualified.
Note that John wrote about making To have the same cv-qualification as From, above. Hence, he called it "copy_cv." Your example, which is perhaps what John meant, is to make sure that To has at least as much cv-qualification as From, without removing any extra To already had. That suggests "augment" or "append." However, if From already is const, copying "const" from To to From won't make From any more const, so "copy" does capture the augmentation idea pretty well. All that to say that I understand your point. The question is whether we need both forms. If so, then we need a way to distinguish the two.
Also, I, too, use an implementation called "propagate_const" and "propagate_cv". To me, "propagate" seems to better evoke the pure addition of qualifiers, whereas "copy" *could* (to some people) mean the overwriting of qualifiers (at least more so than "propagate"):
"Propagate" is probably not a good choice because it doesn't quite imply the addition to existing state you mean, at least to me. Furthermore, "propagate" is frequently misspelled as "propogate." "Augment" seems a bit stilted, but it does capture the idea well. "Add" actually captures the idea pretty well, but we can't use that. If we look at it from the other side, what John wrote above is about replacing From's cv-qualification with that of To, so "replace" works for that, which leaves "copy" for the augmenting form. Therefore, copy_cv, copy_const, copy_volatile make From have at least To's cv-qualification, constness, or volatileness, respectively, while replace_cv, replace_const, and replace_volatile make From have To's cv-qualification, constness, or volatileness, respectively. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Note that John wrote about making To have the same cv-qualification as From, above. Hence, he called it "copy_cv." Your example, which is perhaps what John meant, is to make sure that To has at least as much cv-qualification as From, without removing any extra To already had. That suggests "augment" or "append."
I had intended "copy_cv" to mean: "Make To have the same qualifiers as From". At least intuitively that's what it means to me :-) I hadn't thought about the other form, I guess I'm hoping we don't need both! John.

Stewart, Robert wrote:
Note that John wrote about making To have the same cv-qualification as From, above.
Yes, I realized that shortly after replying :/
However, if From already is const, copying "const" from To to From won't make From any more const, so "copy" does capture the augmentation idea pretty well.
I'm tending to interpret "copy" as overwrite or replace whatever cv qualifiers are on To with whatever is on From, rather than "augment". This might be a stretch, but that seems consistent with the use of the word copy elsewhere, e.g., std::copy.
All that to say that I understand your point. The question is whether we need both forms. If so, then we need a way to distinguish the two.
I think both could be useful. That said, I've only ever used the "propagation"/"augmentation" form.
"Propagate" is probably not a good choice because it doesn't quite imply the addition to existing state you mean, at least to me.
A common meaning of "propagate" is "to pass along to offspring", which seems appropriate enough here. I'll point out that the original poster also chose the word "propagate" independently of myself. Speaking of the OP, I've cc'ed Vasilis back onto this thread (although that's easy to forget to do; I'd encourage Vasilis to either set to receive emails or check the thread yourself.)
Furthermore, "propagate" is frequently misspelled as "propogate."
I understand your concern here., but I consider this a minor issue at best.
"Augment" seems a bit stilted, but it does capture the idea well. "Add" actually captures the idea pretty well, but we can't use that.
Both fail to convey the directionality and "from-to" or "source-dest" nature of the operator.
If we look at it from the other side, what John wrote above is about replacing From's cv-qualification with that of To, so "replace" works for that, which leaves "copy" for the augmenting form.
Therefore, copy_cv, copy_const, copy_volatile make From have at least To's cv-qualification, constness, or volatileness, respectively, while replace_cv, replace_const, and replace_volatile make From have To's cv-qualification, constness, or volatileness, respectively.
I would prefer the replace_* and propagate_* combination, but I'm not gonna go ax someone over it. I'll go along with whatever the maintainer (John?) prefers. - Jeff

Jeffrey Hellrung wrote:
I would prefer the replace_* and propagate_* combination, but I'm not gonna go ax someone over it. I'll go along with whatever the maintainer (John?) prefers.
Actually, on second thought, I'd probably prefer copy_* and propagate_*, given that "replace" seems to have a "search-and-replace" connotation (again, looking at std::replace), which doesn't seem to quite fit here. Now I'm just mumbling... - Jeff

Jeffrey Hellrung wrote:
Stewart, Robert wrote:
However, if From already is const, copying "const" from To to From won't make From any more const, so "copy" does capture the augmentation idea pretty well.
I'm tending to interpret "copy" as overwrite or replace whatever cv qualifiers are on To with whatever is on From, rather than "augment". This might be a stretch, but that seems consistent with the use of the word copy elsewhere, e.g., std::copy.
std::copy doesn't necessarily affect existing elements. The use of "copy" is a bit varied.
"Propagate" is probably not a good choice because it doesn't quite imply the addition to existing state you mean, at least to me.
A common meaning of "propagate" is "to pass along to offspring", which seems appropriate enough here.
But the offspring doesn't have anything not provided by its progenitors. Thus, it isn't augmentation but creation.
I'll point out that the original poster also chose the word "propagate" independently of myself.
I understand, but just as you are concerned about "copy," I'm reporting that "propagate" doesn't help me.
Furthermore, "propagate" is frequently misspelled as "propogate."
I understand your concern here., but I consider this a minor issue at best.
I just wanted to note that folks are likely to make many more mistakes with "propagate" than "copy" that compilers will happily report, but developers will curse.
"Augment" seems a bit stilted, but it does capture the idea well. "Add" actually captures the idea pretty well, but we can't use that.
Both fail to convey the directionality and "from-to" or "source-dest" nature of the operator.
That applies to "copy" and "propagate" just as easily. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Why not transfer_xxx : transfer_cv, transfer_const etc .. ? -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

What about something like
qualify_from< From, To, Interest >
qualify_from<const int, int>::type would be 'const int'
qualify_from<volatile int, int>::type would be 'volatile int'
qualify_from<const volatile int, int, const void>::type would be 'const int'
qualify_from<const volatile int, int, volatile void>::type would be 'volatile int'
and I suppose ...
qualify_from<int, const int>::type could be 'int'

joel falcou wrote:
Why not transfer_xxx :
transfer_cv, transfer_const etc .. ?
That suggests removal from one and application to the other. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On Wed, Mar 03, 2010 at 10:30:47AM -0800, Jeffrey Hellrung wrote: ..[edited]..
Stewart, Robert wrote:
However, if From already is const, copying "const" from To to From won't make From any more const, so "copy" does capture the augmentation idea pretty well.
I'm tending to interpret "copy" as overwrite or replace whatever cv qualifiers are on To with whatever is on From, rather than "augment". This might be a stretch, but that seems consistent with the use of the word copy elsewhere, e.g., std::copy.
I think both could be useful. That said, I've only ever used the "propagation"/"augmentation" form.
Personally, even though the example I presented implements the "augmentation" form, in practice what I had in mind was the "replacement" form. I'm inclined to agree with John here: just have the "replacement" version and call it copy_* (for const / volatile / cv).
Speaking of the OP, I've cc'ed Vasilis back onto this thread (although that's easy to forget to do; I'd encourage Vasilis to either set to receive emails or check the thread yourself.)
Thanks. Yes, in the end it looks like receiving emails is the only workable option. (I ended up following the conversation through gmane, but of course replying becomes complicated.) -- Vasilis Vasaitis "A man is well or woe as he thinks himself so."

Along the same lines... I find I need a "remove_const_ref" template all of the time. For now I have been using a macro RCR() that uses remove_const and remove_ref. There is a balance between having orthogonal features and having convenience features. I don't know where that line is. Surely you do not want to enumerate every possible combination of add/remove. Dan On Mar 2, 2010, at 10:27 AM, Vasilis Vasaitis wrote:
Hello,
I've been looking at the Type Traits library recently, and it looks wonderful overall. However, it's lacking a use case that I end up needing quite often, so I thought I'd suggest it in case the authors and/or other users of the library find it useful. Allow me to explain.
So Type Traits has the add_const / remove_const / is_const triplet (and similar for a few other type properties). add_const is great when you always know that you want to add the const, but sometimes you only want to do it conditionally to another type being const. So recently I've ended up using something like this from quite a few places in my code:
template<class Source, class Target> struct propagate_const { typedef Target type; };
template<class Source, class Target> struct propagate_const<const Source, Target> { typedef const Target type; };
That is, propagate_const<Source, Target> will only add const to Target if Source is const too.
What are the use cases for this? Well, for example recently I was writing an iterator class, and I wanted to avoid duplicating the code for the const_iterator case. Not a big deal, as it turned out, as I could just pass a const type as the template argument and have it behave as the const iterator. The only problem was that I was doing some pointer arithmetic with reinterpret_casts from T* to char* and back (where T is the template argument), so the compiler would complain if T was const. So instead of char I defined this:
typedef typename propagate_const<T, char>::type char_type;
Of course I could also have done this with a combination of is_const and add_const, but this would probably require more code than the propagate_const definition above.
So what do people think? Would it be a useful addition alongside add_* and remove_*?
Thanks, Vasilis
P.S. Please CC me in your replies, as I've set the mailing lists to not send me emails (similar to not being subscribed).
-- Vasilis Vasaitis "A man is well or woe as he thinks himself so."
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Daniel Larimer wrote:
Along the same lines... I find I need a "remove_const_ref" template all of the time. For now I have been using a macro RCR() that uses remove_const and remove_ref. There is a balance between having orthogonal features and having convenience features. I don't know where that line is. Surely you do not want to enumerate every possible combination of add/remove.
and so does remove_all_pointers or remove_all_extents etc. I think such are actually nice addition (more like the has_operator_xxx by Frederic). -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

joel falcou wrote:
and so does remove_all_pointers or remove_all_extents etc. I think such are actually nice addition (more like the has_operator_xxx by Frederic).
Yes, and a remove_pointer<> that also works with smart pointers, a remove_reference<> that works with reference wrappers (and their is_ counterparts), would also be nice extensions IMO. Cheers, Rutger
participants (10)
-
Daniel Larimer
-
Jeffrey Hellrung
-
joel falcou
-
John Maddock
-
John Maddock
-
Matt Calabrese
-
Rutger ter Borg
-
Steven Maitlall
-
Stewart, Robert
-
Vasilis Vasaitis