- **C++**
(*http://www.velocityreviews.com/forums/f39-c.html*)

- - **Forcing all function template parameters to deduce the same type**
(*http://www.velocityreviews.com/forums/t454693-forcing-all-function-template-parameters-to-deduce-the-same-type.html*)

Forcing all function template parameters to deduce the same typeI have the following template to ensure that a given number (val) falls into
a range (between vmin & vmax): template<typename T> T ForceNumericRange( const T& val, const T& vmin, const T& vmax) { T retVal = val; if ( retVal < vmin ) retVal = vmin; else if ( retVal > vmax ) retVal = vmax; return retVal; } Here's the call: float comm; .... comm = ForceNumericRange( comm, 0.0, 100.0); The compiler (Visual Age C++ 5 under AIX 4.3) complains: The function template parameter "T" has been deduced to have two values: "float" and "double" When I took the .0 off the constant parameters, it complained about T being float & int. I solved the problem with this change: comm = ForceNumericRange( comm, 0.0F, 100.0F); but it's hokey, since I don't want the caller to have to explicitly specify the type for the range constants. Is there a way to declare the template such that the types of the 2nd and 3rd parameter are always deduced from the type of the first argument? I'm pretty sure I could give parameters 2 & 3 a different type declaration, and rely on runtime conversions between the different types, but I'd like this resolved at compile time; also, that approach might fail if vmin was a variable and vmax was a constant. Any suggestions? |

Re: Forcing all function template parameters to deduce the same typeDan Krantz <dkrantz@dakran.com> wrote:
>I have the following template to ensure that a given number (val) falls into >a range (between vmin & vmax): >template<typename T> T ForceNumericRange( const T& val, const T& vmin, const >T& vmax) >{ > T retVal = val; > > if ( retVal < vmin ) > retVal = vmin; > else if ( retVal > vmax ) > retVal = vmax; > > return retVal; >} > >Here's the call: > >float comm; >... >comm = ForceNumericRange( comm, 0.0, 100.0); >The compiler (Visual Age C++ 5 under AIX 4.3) complains: The function >template parameter "T" has been deduced to have two values: "float" and >"double" >When I took the .0 off the constant parameters, it complained about T being >float & int. I solved the problem with this change: > >comm = ForceNumericRange( comm, 0.0F, 100.0F); > >but it's hokey, since I don't want the caller to have to explicitly specify >the type for the range constants. >Is there a way to declare the template such that the types of the 2nd and >3rd parameter are always deduced from the type of the first argument? Not that I can think of. My two comments, neither of which answers your question, is that it is uncommon to want to use float instead of double, except when doing I/O or packing data or similar; and that using const Steve to define constants, instead of placing literals in function arguments, is useful. |

Re: Forcing all function template parameters to deduce the same typeIn article <e6ktl2$ebj$1@paola.aioe.org>,
"Dan Krantz" <dkrantz@dakran.com> wrote: > I have the following template to ensure that a given number (val) falls into > a range (between vmin & vmax): > > template<typename T> T ForceNumericRange( const T& val, const T& vmin, const > T& vmax) > { > T retVal = val; > > if ( retVal < vmin ) > retVal = vmin; > else if ( retVal > vmax ) > retVal = vmax; > > return retVal; > } > > Here's the call: > > float comm; > ... > comm = ForceNumericRange( comm, 0.0, 100.0); > > The compiler (Visual Age C++ 5 under AIX 4.3) complains: The function > template parameter "T" has been deduced to have two values: "float" and > "double" > > When I took the .0 off the constant parameters, it complained about T being > float & int. I solved the problem with this change: > > comm = ForceNumericRange( comm, 0.0F, 100.0F); > > but it's hokey, since I don't want the caller to have to explicitly specify > the type for the range constants. > > Is there a way to declare the template such that the types of the 2nd and > 3rd parameter are always deduced from the type of the first argument? I'm > pretty sure I could give parameters 2 & 3 a different type declaration, and > rely on runtime conversions between the different types, but I'd like this > resolved at compile time; also, that approach might fail if vmin was a > variable and vmax was a constant. > > Any suggestions? You can use "concepts" to implement "mixed-mode" arithmetic functions. The first thing you need is a C++03 emulation of concepts: template <bool, class T = void> struct where {}; template <class T> struct where<true, T> {typedef T type;}; This is more famously known as "enable_if" and can be found at www.boost.org. I've also called it "restrict_to" in the past. But it's the same beast whatever you call it. With this struct, and maybe a little help from std::tr1::type_traits (or boost::type_traits) you can constrain your template parameters. In this case you could make all three arguments different template parameters (say T, U and V), but constrain U and V such that they are both convertible to T. That would look like: #include <tr1/type_traits> template <bool, class T = void> struct where {}; template <class T> struct where<true, T> {typedef T type;}; template<typename T, class U, class V> typename where < std::tr1::is_convertible<U, T>::value && std::tr1::is_convertible<V, T>::value, T >::type ForceNumericRange( const T& val, const U& vmin, const V& vmax) { T retVal = val; if ( retVal < vmin ) retVal = vmin; else if ( retVal > vmax ) retVal = vmax; return retVal; } Other constraints might work for you as well. For example you might want to constrain each of T, U and V to be arithmetic types: template<typename T, class U, class V> typename where < std::tr1::is_arithmetic<T>::value && std::tr1::is_arithmetic<U>::value && std::tr1::is_arithmetic<V>::value, T >::type ForceNumericRange( const T& val, const U& vmin, const V& vmax); There is a big push on the standards committee to make concepts part of the language for C++0X. This would clean up the syntax and make it easier to build and reuse complex constraints. If accepted, it will probably use "where" as a keyword. So if you use "where" now, note that it may not compile in the future. You can view this as either a feature or a bug. When it doesn't compile, you'll know it is time to upgrade to the language supported variant. Finally, you could go with 3 unconstrained templates: template<typename T, class U, class V> T ForceNumericRange( const T& val, const U& vmin, const V& vmax); This is what I refer to as "overly generic" code and is prone to breakage in the case that the function name is part of an overload set (if ForceNumericRange is overloaded, even in other namespaces). With a name like ForceNumericRange, unintended overloading seems unlikely. But it is easy to fall into the trap of using overly generic coding techniques with very common names (as was done in the standard): distance advance copy fill rotate -Howard |

Re: Forcing all function template parameters to deduce the same typeIn article
<howard.hinnant-C08735.10214213062006@syrcnyrdrs-02-ge0.nyroc.rr.com>, Howard Hinnant <howard.hinnant@gmail.com> wrote: > You can use "concepts" to implement "mixed-mode" arithmetic functions. > The first thing you need is a C++03 emulation of concepts: > > template <bool, class T = void> struct where {}; > template <class T> struct where<true, T> {typedef T type;}; Oh, I got so carried away with concepts that I neglected to give you one of the simplest techniques. :-) You can do exactly this: > Is there a way to declare the template such that the types of the 2nd and > 3rd parameter are always deduced from the type of the first argument? with the following code: template <class T> struct identity { typedef T type; }; template<typename T> T ForceNumericRange(const T& val, const typename identity<T>::type& vmin, const typename identity<T>::type& vmax); I.e. this puts the second and third arguments into a non-deducible context. And you still have the option of further constraining T using "where" if necessary. -Howard |

All times are GMT. The time now is 08:08 AM. |

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.

SEO by vBSEO ©2010, Crawlability, Inc.