Template subclass trouble

E

ekstrand

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.
 
V

Victor Bazarov

ekstrand said:
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
 
V

Victor Bazarov

ekstrand said:
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
 
J

James Kanze

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.
 
N

Neelesh

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.
 
N

Neelesh

[correcting the usage of words from my previous reply]
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.
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top