
On Fri, Sep 23, 2011 at 4:04 PM, Marshall Clow <mclow.lists@gmail.com>wrote:
On Sep 23, 2011, at 12:01 PM, Jeffrey Lee Hellrung, Jr. wrote:
On Fri, Sep 23, 2011 at 9:34 AM, Marshall Clow <mclow.lists@gmail.com wrote:
On Sep 23, 2011, at 9:21 AM, Phil Endecott wrote:
Dear All,
Some quick comments about the proposed clamp() function:
[...]
Like min & max, clamp has a single type template parameter; what are the implications of this? For example, if I pass a mixture of std::string and const char* arguments, what will happen? Ideally, (a) all combinations would compile, and (b) conversions from const char* to std::string will only happen when necessary, not unconditionally for all of the arguments. (Maybe that is asking too much, though.)
Dunno; I'll put it on the list of things to think about.
Isn't this *precisely* why we have common_type now? :)
I haven't actually looked at the documentation, but I'm gathering that std::less<T> is the default comparison function object, in which case I would suggest this should be replaced with some other function object with a templated operator() that wraps operator<; this should avoid unnecessary temporaries in more cases.
Are you talking about something like this? (typed w/o benefit of compiler)
namespace boost { struct less { typedef bool result_type;
template <typename T> // T models Regular bool operator()(const T& x, const T& y) const { return std::less<T>()(x, y); }
template <typename T, typename U> bool operator ()(const T& x, const U&y) const { return std::less<boost::common_type<T, U>() ( x, y )); } }; }
Hmmm...more like (likewise w/o compiling) template< class T, class L, class U > typename common_type< T const &, L const &, U const & >::type clamp(T const & x, L const & lower, U const & upper) { return x < lower ? lower : upper < x ? upper : x; } for the use of common_type (assuming it accepts 3 parameters, which I seem to remember it did; if not, just nest); and something like struct less { typedef bool result_type; template< class T, class U > bool operator()(T const & x, U const & y) const { return x < y; } }; for the default comparison function object. I don't think using std::less, directly or indirectly, over operator< buys you anything here, does it? While we're on the topic of clamping, I can see where an in-place clamping function would be desirable. Something like template< class T, class L, class U > void clamp_ip(T& x, L const & lower, U const & upper) // ip == "in-place" { if(x < lower) x = lower; else if(upper < x) x = upper; } Could optionally return a T& instead of void, a la operator=. It makes x = clamp(x, lower, upper), which I would consider a common use case, less onerous when x is a long'ish identifier. The in-place clamp also has an outside of chance of being more efficient, as it could require few conversions. Thoughts? - Jeff