This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

g++ template specialization matching problem


                                                  June 23, 2002



      GNU g++,

      I believe that you will find that the following program produces  
an incorrect, result --


#include <iostream>

/* Here are two definitions which can be used used as a template       */
/* parameters.  G is a specific structure.  F is a template for        */
/* generating a set of structures.  In the case of F, it is            */
/* significant that the type of the second template argument, f,       */
/* depends on the first template argument, T.                          */

struct G {};

template <class T, T f> struct F {};

/* X is a structure template parameterized by a single class type      */
/* template parameter. This is its general case.                       */

template <class T> struct X 
{
      X() {cout << "X: general case" << endl;}
};

/* And here is a template which should generate specializations of     */
/* X of a particular form. In this case, the template parameter of     */
/* X is itself generated by a template, namely F.                      */

template <class T, T f> struct X<F<T,f> > 
{
      X() {cout << "X: special case" << endl;}
};

/* f is a simple function                                              */

void f(int) {}

/* The main program creates two instances of X. The first is           */
/* parameterized by G. The second is parameterized by a structure      */
/* generated using the template F.                                     */

/* Note that the constructors of X contain a print statement which     */
/* identifies the template being used.                                 */

/* When the program is compiled using g++ -Wall only the following     */
/* expected warnings are produced --                                   */

/* t2.cpp: In function `int main()':                                      */
/* t2.cpp:62: warning: unused variable `struct X<F<void (*)(int),f> > xf' */
/* t2.cpp:60: warning: unused variable `struct X<G> xg'                   */

/* When the program is run it produces the following output --         */                           

/*    X: general case                                                  */
/*    X: general case                                                  */

/* In other words, the specialization of X intended to be used         */
/* whenever X is parameterized by a structure generated using F,       */
/* though defined, was not found and the general case of X was         */
/* incorrectly used in its place.                                      */

int main()
{
      X<G> xg;

      X<F<void (*)(int), &f> > xf;
}


      -----------


      I mentioned earlier that it is significant that the type of the
second template argument of F, f, depends on the first template
argument, T.  If this is not the case, that is, if F is defined
something like --

      template <class U, class V> struct F {};                            

so that the template parameters are indepndent, and then used in an
analogous way, the problem being reported here does not arise.  Of
course, this rules out using function pointers as template parameters
which was the original goal of the technique.

      I did notice in the "GCC Bugs" document the following statement
referning to "templates" --

      "Two stage lookup is not implemented."                              

but I do not know what this means.  I got the impression that this may
refer to something else.  In any case, I apologize if I have only given
you another example of a known problem.

      With respect to this particular example, I realize it might seem
somewhat obscure.  However, this technique of "pseudo partial
specialization" in which a template class is used in the definition of a
specialization of another template class should, in principle, be quite
helpful in building object wrappers for arbitrary functions.


                                                  WB


PS: g++ -v t2.cpp

Reading specs from /usr/local/lib/gcc-lib/i586-pc-linux-gnu/2.95.2/specs
gcc version 2.95.2 19991024 (release)
 /usr/local/lib/gcc-lib/i586-pc-linux-gnu/2.95.2/cpp -lang-c++ -v -D__GNUC__=2 -D__GNUG__=2 -D__GNUC_MINOR__=95 -D__cplusplus -D__ELF__ -Dunix -D__i386__ -Dlinux -D__ELF__ -D__unix__ -D__i386__ -D__linux__ -D__unix -D__linux -Asystem(posix) -D__EXCEPTIONS -Acpu(i386) -Amachine(i386) -Di386 -D__i386 -D__i386__ -Di586 -Dpentium -D__i586 -D__i586__ -D__pentium -D__pentium__ t2.cpp /tmp/ccngjPti.ii
GNU CPP version 2.95.2 19991024 (release) (i386 Linux/ELF)
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/lib/gcc-lib/i586-pc-linux-gnu/2.95.2/../../../../include/g++-3
 /usr/local/include
 /usr/local/lib/gcc-lib/i586-pc-linux-gnu/2.95.2/../../../../i586-pc-linux-gnu/include
 /usr/local/lib/gcc-lib/i586-pc-linux-gnu/2.95.2/include
 /usr/include
End of search list.
The following default directories have been omitted from the search path:
End of omitted list.
 /usr/local/lib/gcc-lib/i586-pc-linux-gnu/2.95.2/cc1plus /tmp/ccngjPti.ii -quiet -dumpbase t2.cc -version -o /tmp/ccoOLNMt.s
GNU C++ version 2.95.2 19991024 (release) (i586-pc-linux-gnu) compiled by GNU C version 2.95.2 19991024 (release).
 as -V -Qy -o /tmp/ccjpHHq0.o /tmp/ccoOLNMt.s
GNU assembler version 2.9.1 (i386-redhat-linux), using BFD version 2.9.1.0.23
 /usr/local/lib/gcc-lib/i586-pc-linux-gnu/2.95.2/collect2 -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /usr/local/lib/gcc-lib/i586-pc-linux-gnu/2.95.2/crtbegin.o -L/usr/local/lib/gcc-lib/i586-pc-linux-gnu/2.95.2 -L/usr/local/lib /tmp/ccjpHHq0.o -lstdc++ -lm -lgcc -lc -lgcc /usr/local/lib/gcc-lib/i586-pc-linux-gnu/2.95.2/crtend.o /usr/lib/crtn.o


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]