Re: Function templates

From: Rob Williscroft (rtw_at_freenet.REMOVE.co.uk)
Date: 01/05/04


Date: 05 Jan 2004 15:34:51 GMT

Howard Hinnant wrote in news:hinnant-36EA5C.08564805012004@syrcnyrdrs-01-
ge0.nyroc.rr.com:

> In article <vo8Kb.15831$ws.1748349@news02.tsnz.net>,
> Jacques Labuschagne <jacques@clawshrimp.com> wrote:
>
>> You can't restrict T, but you can use T in
>> such a way that it only compiles with compatible types.
>
> You can also restrict T for the purpose of guiding overload resolution
> (though it is far from clear that that is what the OP needed). Search
> for "restrict_to" and "enable_if".
>

It actually doesn't do a bad job at all:

g++ -O2 -W -Wall -pedantic -ansi -o test-gcc.exe test.cpp
compiling:
test.cpp: In function `int main()':
test.cpp:76: no matching function for call to `SQ(A)'

cl /W3 /Za /Zc:forScope,wchar_t /GR /O2 /TP /EHs test.cpp
compiling:
test.cpp
test.cpp:76: error C2893: Failed to specialize function template
'restrict_to<T,
can_multiply<T>::value>::type SQ(const T &)'
        With the following template arguments:
        'A'

bccx -O2 -w-8027 -otest-cbx.exe test.cpp
compiling:
Borland C++ 6.0 Preview for Win32 Copyright (c) 1993, 2003 Borland
Error test.cpp 76: no instance of function template "SQ" matches the
argument list

A lot of typing for a clean error message though:

#include <iostream>
#include <ostream>
#include <iomanip>

namespace detail
{
  struct unique {};

  typedef char False;
  typedef char (&True)[2];

  template < typename T >
  unique operator * ( T const &, T const & );

  template < typename X >
  False is_unique( X const & );
  True is_unique( unique );

  template < typename T > T const &c_ref();

  /* Simplistic implementation, doesn't check wether
     T * T is convertable to T
  */
  template < typename T > struct can_multiply
  {
    static bool const value =
      sizeof( is_unique( c_ref< T >() * c_ref< T >() ) )
      ==
      sizeof( False )
    ;
  };
} /* detail:: */

template < typename T >
struct can_multiply : detail::can_multiply< T >
{
};

template < typename T, bool False > struct restrict_to
{
};
template < typename T> struct restrict_to< T, true >
{
  typedef T type;
};

template < typename T >
typename restrict_to< T, can_multiply< T >::value >::type
  SQ( T const &a )
{
  return a * a;
}

struct A {};

#define FAIL

int main()
{
  using namespace std;

  cerr << boolalpha;

  cerr << can_multiply< int >::value << '\n';
  cerr << can_multiply< A >::value << '\n';

  cerr << SQ( 3 ) << '\n';

#if defined( FAIL )

  cerr << SQ ( A() ) << '\n'; // line 76

#endif
}

Rob.

-- 
http://www.victim-prime.dsl.pipex.com/


Relevant Pages