Template subclass trouble

Discussion in 'C++' started by ekstrand, May 14, 2009.

  1. ekstrand

    ekstrand Guest

    I am having problems with subclassing a templated class with a
    templated subclass. Consider the following program (I have simplified
    it greatly from its origional form, the actual header file can be
    provided upon request):


    class A
    {
    public:
    static void f() { }
    };

    template<typename T, typename Q>
    class B
    {
    public:
    B(T* t = 0) { }
    B(B& b) { }
    ~B() { Q::f(); }
    };

    template<typename T>
    class C:
    public B<T, A>
    {
    public:
    C(T* t = 0): B<T, A>(t) { }
    C(C& c): B<T, A>(c) { }
    };

    C<int>
    function() {
    C<int> var;
    return var;
    }

    int main()
    {
    C<int> var = function();
    return 0;
    }

    I have a class that takes two template parameters. In order to specify
    one of these template parameters without specifying the other, I
    create a second templated class that is a subclass of the other. This
    method seems to be the generally accepted method for getting around
    the no templated typedefs problem. However, when I try to build it
    with g++, I get the following error message:

    template_test.cpp: In function ‘int main()’:
    template_test.cpp:33: error: no matching function for call to
    ‘C<int>::C(C<int>)’
    template_test.cpp:22: note: candidates are: C<T>::C(C<T>&) [with T =
    int]
    template_test.cpp:21: note: C<T>::C(T*) [with T = int]

    g++ cannot find the copy constructor even though the first candidate
    is exactly what it needs. If I make the copy constructor const, the
    problem goes away. Also, this code correctly builds on VisualC++ 2005.
    Is there something I'm missing, or have I found a bug in g++?

    My g++ version is as follows:
    Using built-in specs.
    Target: i486-linux-gnu
    Configured with: ../src/configure -v --with-pkgversion='Debian
    4.3.2-1.1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --
    enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-
    shared --with-system-zlib --libexecdir=/usr/lib --without-included-
    gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/
    usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --
    enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-
    targets=all --enable-cld --enable-checking=release --build=i486-linux-
    gnu --host=i486-linux-gnu --target=i486-linux-gnu
    Thread model: posix
    gcc version 4.3.2 (Debian 4.3.2-1.1)

    Thanks in advance for your response.
    ekstrand, May 14, 2009
    #1
    1. Advertising

  2. ekstrand wrote:
    > I am having problems with subclassing a templated class with a
    > templated subclass. Consider the following program (I have simplified
    > it greatly from its origional form, the actual header file can be
    > provided upon request):
    >
    >
    > class A
    > {
    > public:
    > static void f() { }
    > };
    >
    > template<typename T, typename Q>
    > class B
    > {
    > public:
    > B(T* t = 0) { }
    > B(B& b) { }
    > ~B() { Q::f(); }
    > };
    >
    > template<typename T>
    > class C:
    > public B<T, A>
    > {
    > public:
    > C(T* t = 0): B<T, A>(t) { }
    > C(C& c): B<T, A>(c) { }
    > };
    >
    > C<int>
    > function() {
    > C<int> var;
    > return var;
    > }
    >
    > int main()
    > {
    > C<int> var = function();
    > return 0;
    > }
    >
    > I have a class that takes two template parameters. In order to specify
    > one of these template parameters without specifying the other, I
    > create a second templated class that is a subclass of the other. This
    > method seems to be the generally accepted method for getting around
    > the no templated typedefs problem. However, when I try to build it
    > with g++, I get the following error message:
    >
    > template_test.cpp: In function ‘int main()’:
    > template_test.cpp:33: error: no matching function for call to
    > ‘C<int>::C(C<int>)’
    > template_test.cpp:22: note: candidates are: C<T>::C(C<T>&) [with T =
    > int]
    > template_test.cpp:21: note: C<T>::C(T*) [with T = int]
    >
    > g++ cannot find the copy constructor even though the first candidate
    > is exactly what it needs. If I make the copy constructor const, the
    > problem goes away. Also, this code correctly builds on VisualC++ 2005.
    > Is there something I'm missing, or have I found a bug in g++?
    >
    > My g++ version is as follows:
    > Using built-in specs.
    > Target: i486-linux-gnu
    > Configured with: ../src/configure -v --with-pkgversion='Debian
    > 4.3.2-1.1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --
    > enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-
    > shared --with-system-zlib --libexecdir=/usr/lib --without-included-
    > gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/
    > usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --
    > enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-
    > targets=all --enable-cld --enable-checking=release --build=i486-linux-
    > gnu --host=i486-linux-gnu --target=i486-linux-gnu
    > Thread model: posix
    > gcc version 4.3.2 (Debian 4.3.2-1.1)
    >
    > Thanks in advance for your response.


    This has nothing to do with templates. Try this

    class A {
    public:
    A(A&) {}
    };

    A foo() {
    A a;
    return a;
    }

    int main() {
    A aa = foo();
    }

    The problem is that you're trying to initialise 'aa' using a temporary
    returned from 'foo'. To do that a copy constructor would be used. You
    defined a copy constructor that takes a reference to non-const 'A'. A
    temporary cannot be bound to a reference to non-const. Period.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, May 14, 2009
    #2
    1. Advertising

  3. ekstrand wrote:
    > I am having problems with subclassing a templated class with a
    > templated subclass. Consider the following program (I have simplified
    > it greatly from its origional form, the actual header file can be
    > provided upon request):
    >
    >
    > class A
    > {
    > public:
    > static void f() { }
    > };
    >
    > template<typename T, typename Q>
    > class B
    > {
    > public:
    > B(T* t = 0) { }
    > B(B& b) { }
    > ~B() { Q::f(); }
    > };
    >
    > template<typename T>
    > class C:
    > public B<T, A>
    > {
    > public:
    > C(T* t = 0): B<T, A>(t) { }
    > C(C& c): B<T, A>(c) { }
    > };
    >
    > C<int>
    > function() {
    > C<int> var;
    > return var;
    > }
    >
    > int main()
    > {
    > C<int> var = function();
    > return 0;
    > }
    >
    > I have a class that takes two template parameters. In order to specify
    > one of these template parameters without specifying the other, I
    > create a second templated class that is a subclass of the other. This
    > method seems to be the generally accepted method for getting around
    > the no templated typedefs problem. However, when I try to build it
    > with g++, I get the following error message:
    >
    > template_test.cpp: In function ‘int main()’:
    > template_test.cpp:33: error: no matching function for call to
    > ‘C<int>::C(C<int>)’
    > template_test.cpp:22: note: candidates are: C<T>::C(C<T>&) [with T =
    > int]
    > template_test.cpp:21: note: C<T>::C(T*) [with T = int]
    >
    > g++ cannot find the copy constructor even though the first candidate
    > is exactly what it needs. If I make the copy constructor const, the
    > problem goes away. Also, this code correctly builds on VisualC++ 2005.
    > Is there something I'm missing, or have I found a bug in g++?
    >
    > My g++ version is as follows:
    > Using built-in specs.
    > Target: i486-linux-gnu
    > Configured with: ../src/configure -v --with-pkgversion='Debian
    > 4.3.2-1.1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --
    > enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-
    > shared --with-system-zlib --libexecdir=/usr/lib --without-included-
    > gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/
    > usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --
    > enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-
    > targets=all --enable-cld --enable-checking=release --build=i486-linux-
    > gnu --host=i486-linux-gnu --target=i486-linux-gnu
    > Thread model: posix
    > gcc version 4.3.2 (Debian 4.3.2-1.1)
    >
    > Thanks in advance for your response.


    This has nothing to do with templates. Try this

    class A {
    public:
    A() {}
    A(A&) {}
    };

    A foo() {
    A a;
    return a;
    }

    int main() {
    A aa = foo();
    }

    The problem is that you're trying to initialise 'aa' using a temporary
    returned from 'foo'. To do that a copy constructor would be used. You
    defined a copy constructor that takes a reference to non-const 'A'. A
    temporary cannot be bound to a reference to non-const. Period.

    Visual C++ is lax. Try disabling language extensions in it.

    You found a hole in Visual C++, not a bug in gcc.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, May 14, 2009
    #3
  4. ekstrand

    James Kanze Guest

    On May 14, 2:39 am, ekstrand <> wrote:
    > I am having problems with subclassing a templated class with a
    > templated subclass. Consider the following program (I have
    > simplified it greatly from its origional form, the actual
    > header file can be provided upon request):


    > class A
    > {
    > public:
    > static void f() { }
    > };


    > template<typename T, typename Q>
    > class B
    > {
    > public:
    > B(T* t = 0) { }
    > B(B& b) { }
    > ~B() { Q::f(); }
    > };


    > template<typename T>
    > class C:
    > public B<T, A>
    > {
    > public:
    > C(T* t = 0): B<T, A>(t) { }
    > C(C& c): B<T, A>(c) { }
    > };


    > C<int>
    > function() {
    > C<int> var;
    > return var;
    > }


    > int main()
    > {
    > C<int> var = function();
    > return 0;
    > }


    > I have a class that takes two template parameters. In order to
    > specify one of these template parameters without specifying
    > the other, I create a second templated class that is a
    > subclass of the other. This method seems to be the generally
    > accepted method for getting around the no templated typedefs
    > problem. However, when I try to build it with g++, I get the
    > following error message:


    > template_test.cpp: In function ‘int main()’:
    > template_test.cpp:33: error: no matching function for call to
    > ‘C<int>::C(C<int>)’
    > template_test.cpp:22: note: candidates are: C<T>::C(C<T>&) [with T =
    > int]
    > template_test.cpp:21: note: C<T>::C(T*) [with T = int]


    > g++ cannot find the copy constructor even though the first
    > candidate is exactly what it needs.


    G++ finds the copy constructor. The problem is that your copy
    constructor prevents the compiler from generating one, and that
    your copy constructor can't be used here, since it takes a
    non-const reference (which can only be initialized by an
    lvalue).

    > If I make the copy constructor const, the problem goes away.


    In other words, you know what's wrong with your code.

    > Also, this code correctly builds on VisualC++ 2005. Is there
    > something I'm missing, or have I found a bug in g++?


    A bug in VC++, rather. Your code isn't legal, and shouldn't
    compile.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, May 14, 2009
    #4
  5. ekstrand

    Neelesh Guest

    On May 14, 5:39 am, ekstrand <> wrote:
    > I am having problems with subclassing a templated class with a
    > templated subclass. Consider the following program (I have simplified
    > it greatly from its origional form, the actual header file can be
    > provided upon request):
    >
    > class A
    > {
    > public:
    >         static void f() { }
    >
    > };
    >
    > template<typename T, typename Q>
    > class B
    > {
    > public:
    >         B(T* t = 0) { }
    >         B(B& b) { }
    >         ~B() { Q::f(); }
    >
    > };
    >
    > template<typename T>
    > class C:
    >         public B<T, A>
    > {
    > public:
    >         C(T* t = 0): B<T, A>(t) { }
    >         C(C& c): B<T, A>(c) { }
    >
    > };
    >
    > C<int>
    > function() {
    >         C<int> var;
    >         return var;
    >
    > }
    >
    > int main()
    > {
    >         C<int> var = function();
    >         return 0;
    >
    > }
    >
    > I have a class that takes two template parameters. In order to specify
    > one of these template parameters without specifying the other, I
    > create a second templated class that is a subclass of the other. This
    > method seems to be the generally accepted method for getting around
    > the no templated typedefs problem. However, when I try to build it
    > with g++, I get the following error message:
    >
    > template_test.cpp: In function ‘int main()’:
    > template_test.cpp:33: error: no matching function for call to
    > ‘C<int>::C(C<int>)’
    > template_test.cpp:22: note: candidates are: C<T>::C(C<T>&) [with T =
    > int]
    > template_test.cpp:21: note:                 C<T>::C(T*) [with T = int]
    >
    > g++ cannot find the copy constructor even though the first candidate
    > is exactly what it needs. If I make the copy constructor const, the
    > problem goes away.


    No, making the "copy constructor const" doesn't solve the problem,
    but "making the copy constructor take a const reference" does.
    Neelesh, May 14, 2009
    #5
  6. ekstrand

    Neelesh Guest

    [correcting the usage of words from my previous reply]
    On May 14, 2:10 pm, Neelesh <> wrote:
    >
    > > I have a class that takes two template parameters. In order to specify
    > > one of these template parameters without specifying the other, I
    > > create a second templated class that is a subclass of the other. This
    > > method seems to be the generally accepted method for getting around
    > > the no templated typedefs problem. However, when I try to build it
    > > with g++, I get the following error message:

    >
    > > template_test.cpp: In function ‘int main()’:
    > > template_test.cpp:33: error: no matching function for call to
    > > ‘C<int>::C(C<int>)’
    > > template_test.cpp:22: note: candidates are: C<T>::C(C<T>&) [with T =
    > > int]
    > > template_test.cpp:21: note:                 C<T>::C(T*) [with T = int]

    >
    > > g++ cannot find the copy constructor even though the first candidate
    > > is exactly what it needs. If I make the copy constructor const, the
    > > problem goes away.

    >

    No, making  the "copy constructor const" doesn't solve the problem,
    but "making the copy constructor take a reference to const" does.
    Neelesh, May 14, 2009
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. jstorta
    Replies:
    3
    Views:
    428
    jstorta
    Feb 20, 2006
  2. Pyenos
    Replies:
    9
    Views:
    278
    WaterWalk
    Dec 29, 2006
  3. S.Volkov
    Replies:
    2
    Views:
    205
    S.Volkov
    Mar 12, 2006
  4. Trans
    Replies:
    8
    Views:
    307
    Robert Klemme
    Oct 23, 2008
  5. Fab

    Subclass of subclass

    Fab, Aug 9, 2012, in forum: C++
    Replies:
    0
    Views:
    383
Loading...

Share This Page