12

I was checking the implementation of clamp in boost:

  template<typename T, typename Pred> 
  T const & clamp ( T const& val, 
    typename boost::mpl::identity<T>::type const & lo, 
    typename boost::mpl::identity<T>::type const & hi, Pred p )
  {
//    assert ( !p ( hi, lo ));    // Can't assert p ( lo, hi ) b/c they might be equal
    return p ( val, lo ) ? lo : p ( hi, val ) ? hi : val;
  } 

If I look up the documentation, identity returns the template argument unchanged.

The identity metafunction. Returns X unchanged.

So what's the point of using it here?

Isn't typename boost::mpl::identity<T>::type equivalent to T?

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176

1 Answers1

15

A nested-name-specifier creates a non-deduced context. Therefore, a compiler will not attempt to deduce type T based on the second and third parameters declared as:

typename boost::mpl::identity<T>::type const &

Type T will be deduced only based on the type of the first argument, and then used to instantiate the types of the rest parameters. Using the identity type is a common trick to prevent template argument type deduction on certain parameters, that otherwise would result in an ambiguous call error in case the types of arguments differ, but utilize the same type template parameter. It can be also sometimes desired not to let a compiler automatically infer the type, and force a caller do it on his/her own.

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
  • Is there any other away to achieve the same result? (Outside of I guess writing another function and casting the `lo` and `hi`) – Barry Nov 12 '14 at 11:55
  • 1
    @Barry no doubt, because there are similar ways to create non-deducible context. However, few will be as elegant and idiomatic as this. So, why would you want it any other way? (If you don't like MPL, just write the `identity` meta function yourself. It's all of ~6 lines of code) – sehe Nov 12 '14 at 12:36
  • 4
    +1 One nitpick: you might want to mention that using the nested `::type` in a non-deduced context allows implicit conversions on `hi` and `lo`, which are not considered during argument deduction. Allowing such mixed parameter types would be the major application here. – TemplateRex Nov 12 '14 at 12:50
  • 1
    @sehe Just curiosity. No issues with MPL. Althuogh why does just `template using alias = T` not count as a non-deduced context? – Barry Nov 12 '14 at 13:36
  • 1
    @Barry Because it's just an alias, no instantiation – sehe Nov 12 '14 at 13:38