Topic: Template instantiation - nonsensical member functions


Author: bglenden@colobus.cv.nrao.edu (Brian Glendenning)
Date: Mon, 29 Mar 1993 13:39:29 GMT
Raw View
My understanding of the template instantiation "philosophy" of C++
(e.g. an article in the latest "C++ Report") is that member functions
are only instantiated if they are used. For example, given a templated
vector type:

Vector<int>    vi(10);
Vector<String> vs(10);
vi(3) = 3;
vs(3) = "three";
vi -= 1;        // Decrement each element of vi by 1

is all OK, but
vs -= "Foo";

Would cause a problem (presuming that -= isn't defined for Strings).
However in my CFront 3.0 based implementation (Sun version 2.0.1) it
doesn't seem to behave this way, i.e. even though I don't use -=
anywhere, I get an error like:

"./vector.C", line 22: error: bad operands for -=: String -= const String
"./vector.C", line 22:   error detected during the instantiation of
Vector <String>

The only relevant flags appear to be -pts and -pta, neither one of
which appear to do the job.

So;

1. Is my understanding correct, is it the intention of the C++
   standardization to "bless" having templates some of whose member
   functions don't make sense for all types; and

2. How do I actually do this with current versions of CFront.

[For this toy problem a solution would be to derive a "numeric Vector"
>from a "storage Vector"; for the real problem the consequences would
be worse, among other things likely requiring MI.]

Thanks,
Brian
--
       Brian Glendenning - National Radio Astronomy Observatory
bglenden@nrao.edu          Charlottesville Va.           (804) 296-0286




Author: bglenden@colobus.cv.nrao.edu (Brian Glendenning)
Date: Mon, 29 Mar 1993 18:34:32 GMT
Raw View
In article <BGLENDEN.93Mar29083929@colobus.cv.nrao.edu> bglenden@colobus.cv.nrao.edu (Brian Glendenning) writes:
[ Question about when template member functions are instantiated; i.e.
only when used? ]

Here's a small example that I think should compile but doesn't:

#!/bin/sh
# This is a shell archive (shar 3.24)
# made 03/29/1993 18:34 UTC by bglenden@colobus
# Source directory /colobus/aips/pgmr/bglenden/tmp/vector
#
# existing files WILL be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#     76 -rw-r--r-- foo.C
#    177 -rw-r--r-- foo.h
#    414 -rw-r--r-- main.C
#    390 -rw-r--r-- vector.C
#    254 -rw-r--r-- vector.h
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= foo.C ==============
echo "x - extracting foo.C (Text)"
sed 's/^X//' << 'SHAR_EOF' > foo.C &&
X#include "foo.h"
X
XFoo::Foo()
X{
X        just_so_we_have_a_data_member = 0;
X}
SHAR_EOF
$TOUCH -am 0326160493 foo.C &&
chmod 0644 foo.C ||
echo "restore of foo.C failed"
set `wc -c foo.C`;Wc_c=$1
if test "$Wc_c" != "76"; then
 echo original size 76, current size $Wc_c
fi
# ============= foo.h ==============
echo "x - extracting foo.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > foo.h &&
X// Just a class that cannot be used numerically
X
X#if !defined (FOO_H)
X#define FOO_H
X
Xclass Foo {
Xpublic:
X    Foo();
Xprivate:
X    char *just_so_we_have_a_data_member;
X};
X
X#endif
SHAR_EOF
$TOUCH -am 0326160393 foo.h &&
chmod 0644 foo.h ||
echo "restore of foo.h failed"
set `wc -c foo.h`;Wc_c=$1
if test "$Wc_c" != "177"; then
 echo original size 177, current size $Wc_c
fi
# ============= main.C ==============
echo "x - extracting main.C (Text)"
sed 's/^X//' << 'SHAR_EOF' > main.C &&
X#include "vector.h"
X#include "foo.h"
X#include <iostream.h>
X#include <assert.h>
X
Xmain()
X{
X    Vector<int> vi(10);
X    for (int i=0; i < 10; i++) {
X vi(i) = i;
X assert(vi(i) == i);
X    }
X    vi -= 1;
X    for (i=0; i < 10; i++) {
X assert(vi(i) == i - 1);
X    }
X
X    Vector<Foo> vf(10); // Causes compilation to bar because -= is not defined
X                        // for Foos.
X
X
X    cout << "OK\n";
X    return 0;
X
X}
SHAR_EOF
$TOUCH -am 0329133393 main.C &&
chmod 0644 main.C ||
echo "restore of main.C failed"
set `wc -c main.C`;Wc_c=$1
if test "$Wc_c" != "414"; then
 echo original size 414, current size $Wc_c
fi
# ============= vector.C ==============
echo "x - extracting vector.C (Text)"
sed 's/^X//' << 'SHAR_EOF' > vector.C &&
X#include "vector.h"
X
Xtemplate<class T> Vector<T>::Vector(int size)
X{
X    data = new T[size];
X    length = size;
X}
X
Xtemplate<class T> Vector<T>::~Vector()
X{
X    delete data;
X}
X
Xtemplate<class T> T &Vector<T>::operator()(int index)
X{
X    return *(data + index);
X}
X
Xtemplate<class T> void Vector<T>::operator-=(const T &val)
X{
X    for (int i=0; i < length; i++) {
X *(data + i) -= val;
X    }
X}
SHAR_EOF
$TOUCH -am 0326161993 vector.C &&
chmod 0644 vector.C ||
echo "restore of vector.C failed"
set `wc -c vector.C`;Wc_c=$1
if test "$Wc_c" != "390"; then
 echo original size 390, current size $Wc_c
fi
# ============= vector.h ==============
echo "x - extracting vector.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > vector.h &&
X// Toy Vector class
X
X#if !defined(VECTOR_H)
X#define VECTOR_H
X
Xtemplate<class T> class Vector {
Xpublic:
X    Vector(int size);
X    ~Vector();
X    T &operator()(int index);
X    void operator-=(const T &val);
Xprivate:
X    int length;
X    T *data;
X};
X
X#endif
SHAR_EOF
$TOUCH -am 0326161793 vector.h &&
chmod 0644 vector.h ||
echo "restore of vector.h failed"
set `wc -c vector.h`;Wc_c=$1
if test "$Wc_c" != "254"; then
 echo original size 254, current size $Wc_c
fi
exit 0
--
       Brian Glendenning - National Radio Astronomy Observatory
bglenden@nrao.edu          Charlottesville Va.           (804) 296-0286