Function templates

A

al

1. If a function template is defined:

template <typename A>
A SQ(A& a)
{
return a*a;
}

How could prevent users from passing a type which makes no sense, like
Employee class type?

2. If Employee is pass as T in the template below, should an assignment
operator have to be defined since there're assignment operation in the
function?

template <class T>
void swap(T& x, T& y)
{
T temp;
temp = x;
x = y;
y = temp;
}

3. Is "template <class T>" equivalent to "template <typename T>"?

Thanks!
 
R

Ron Natalie

al said:
1. If a function template is defined:

How could prevent users from passing a type which makes no sense, like
Employee class type?

You can't, anymore than you can stop them from writing
Employee() * Employee()
other than the compiler bitching about * not being defined for those
types.
2. If Employee is pass as T in the template below, should an assignment
operator have to be defined since there're assignment operation in the
function?

There has to be one accessible. Of course, operator= will be defined
in a class if the user doesn't declare one.
3. Is "template <class T>" equivalent to "template <typename T>"?

Yes. <class T> will match any type, not just class types. Typename
and class are interchangeable in this context.
 
C

Cy Edmunds

al said:
1. If a function template is defined:

template <typename A>
A SQ(A& a)
{
return a*a;
}

How could prevent users from passing a type which makes no sense, like
Employee class type?

Let 'em try. It won't compile. Of course the error message may be a bit
obscure.
2. If Employee is pass as T in the template below, should an assignment
operator have to be defined since there're assignment operation in the
function?

template <class T>
void swap(T& x, T& y)
{
T temp;
temp = x;
x = y;
y = temp;
}

If you don't write an assignment operator the compiler will provide you with
one which just copies the bits.
3. Is "template <class T>" equivalent to "template <typename T>"?

Yes. The keyword "typename" was a relatively late addition to the language.
It makes more sense in this context then "class".
 
G

Gianni Mariani

al said:
1. If a function template is defined:

template <typename A>
A SQ(A& a)
{
return a*a;
}

How could prevent users from passing a type which makes no sense, like
Employee class type?

You can create a specialization like:

template <typename A>
A SQ(A& a)
{
return a*a;
}

template <>
Employee SQ(Employee& a)
{
... some code that compiles to an error ...
}

However if you don't provide a 'operator *()', your original SQ provides
for an error anyway.
 
R

Ron Natalie

Cy Edmunds said:
If you don't write an assignment operator the compiler will provide you with
one which just copies the bits.

Well, more specifically, it invokes the assignment semantics of all the subobjects
(bases and non-static members).
 
C

Cy Edmunds

Ron Natalie said:
Well, more specifically, it invokes the assignment semantics of all the subobjects
(bases and non-static members).

Right! When I first started C++ I worried about that.
 
J

Jeff Schwab

al said:
1. If a function template is defined:

template <typename A>
A SQ(A& a)
{
return a*a;
}

How could prevent users from passing a type which makes no sense, like
Employee class type?

That won't compile for any type without a binary * operator. What you
really want is called a "constraint." I don't know of a great way to
specify constraints in C++.
2. If Employee is pass as T in the template below, should an assignment
operator have to be defined since there're assignment operation in the
function?

template <class T>
void swap(T& x, T& y)
{
T temp;
temp = x;
x = y;
y = temp;
}

Yes, an assignment operator must be defined, but it may be the default.

You could avoid one of the assignments by initalizing temp properly:

T temp = x;

There are good reasons to prefer this technique to the one in your example.

Are you writing your own library? If not, you may want to use the
existing swap template in the standard library. The STL swap has been
specialized for important cases (e.g. vectors).
3. Is "template <class T>" equivalent to "template <typename T>"?

Yup, although I've had problems (in the past) with both versions on
different compilers. Recent compilers seem okay with both; I prefer
"typename," since T may not be a class.
 
C

Chris Mantoulidis

Cy Edmunds said:
Let 'em try. It won't compile. Of course the error message may be a bit
obscure.


If you don't write an assignment operator the compiler will provide you with
one which just copies the bits.


Yes. The keyword "typename" was a relatively late addition to the language.
It makes more sense in this context then "class".


So, <class T> allows ANY KINDA class and type (int, char, etc.) to be
passed as the template whereas <template T> allows just types?? Is
that it? Cuz I'm a bit confused.

TIA,
cmad
 
J

Jacques Labuschagne

Chris said:
So, <class T> allows ANY KINDA class and type (int, char, etc.) to be
passed as the template whereas <template T> allows just types?? Is
that it? Cuz I'm a bit confused.

No, the two are equivalent. You can't restrict T, but you can use T in
such a way that it only compiles with compatible types.

template<typename T>
void foo(const T& some_object){
some_object.unusual_function();
}

or even

template<typename T>
T bar(const T& some_object){
T other_object; // requires T default constructable.
other_object = some_object; // requires T copyable.
return some_object + other_object; // requires operator+
}
 
R

Rolf Magnus

Chris said:
So, <class T> allows ANY KINDA class and type (int, char, etc.) to be
passed as the template whereas <template T> allows just types??

What do you mean by "just types"? classes _are_ types.
Is that it? Cuz I'm a bit confused.

Again, there is no difference between <class T> and <typename T> (not
<template T> btw - I guess that was a typo).
 
C

Chris Mantoulidis

Jacques Labuschagne said:
No, the two are equivalent. You can't restrict T, but you can use T in
such a way that it only compiles with compatible types.

compatible types = int, char, etc. ???


Then what's the difference between typename and class... You don't really explain

Thanks,
cmad
 
J

Jacques Labuschagne

Chris said:
compatible types = int, char, etc. ???

Compatible types == ones supporting the required operations (assignment,
default construction, etc). There's no difference between fundamental
types (int, char, etc) and user-defined types from a template's point of
view.
Then what's the difference between typename and class... You don't really explain

I said the two are equivalent. There is no difference.

Jacques.
 
H

Howard Hinnant

Jacques Labuschagne said:
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".

-Howard
 
R

Rob Williscroft

Howard Hinnant wrote in ge0.nyroc.rr.com:
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.
 
C

Chris Mantoulidis

Jacques Labuschagne said:
Compatible types == ones supporting the required operations (assignment,
default construction, etc). There's no difference between fundamental
types (int, char, etc) and user-defined types from a template's point of
view.


I said the two are equivalent. There is no difference.

Jacques.

Then no need to have 2 (class & typename) is there?
 
H

Howard Hinnant

Rob Williscroft said:
It actually doesn't do a bad job at all: ....
A lot of typing for a clean error message though:

<chuckle> Yup!

For better error messages I see no better solution that static_assert:

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1381.htm

restrict_to is good for cases when what you want is not an error
message, but rather the selection of another overload (possibly one
you're not even aware of when you write your restricted template
function). Maybe something like:

template < typename T >
typename restrict_to
<
T,
can_multiply said:
square( T const &a )
{
return a * a;
}

template < typename T >
typename restrict_to
<
void,
can_dance said:
square( T &a )
{
...
}

-Howard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,159
Messages
2,570,883
Members
47,414
Latest member
djangoframe

Latest Threads

Top