473,473 Members | 1,853 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

[templates] is this code legal?

Is it legal, in a class template's member function, to instantiate the same
class template but with a different type as argument? The following code is
very simple and I'd expect it to compile, but it makes both MSVC and gcc
freeze and never return. Sometimes I get an "internal compiler error"
instead.

struct Instance_base
{
virtual ~Instance_base() {}
virtual Instance_base* mkptr() = 0;
};

template<typename T>
struct Instance: Instance_base
{
T _inst;
Instance(const T &v): _inst(v) {}
Instance_base* mkptr() { return new Instance<T*>(&_inst); }
};

Instance_base* inst = new Instance<int>(3);
The offending line is that of Instance::mkptr(), if I remove it (and I make
the base class' method non-abstract) everything compiles ifne. Any clues?

Cheers,
Marco
Sep 19 '05 #1
9 1455
* Marco Jez:
Is it legal, in a class template's member function, to instantiate the same
class template but with a different type as argument?
Yes.

The following code is
very simple and I'd expect it to compile, but it makes both MSVC and gcc
freeze and never return. Sometimes I get an "internal compiler error"
instead.

struct Instance_base
{
virtual ~Instance_base() {}
virtual Instance_base* mkptr() = 0;
};

template<typename T>
struct Instance: Instance_base
{
T _inst;
Instance(const T &v): _inst(v) {}
Instance_base* mkptr() { return new Instance<T*>(&_inst); }
};

Instance_base* inst = new Instance<int>(3);
The offending line is that of Instance::mkptr(), if I remove it (and I make
the base class' method non-abstract) everything compiles ifne. Any clues?


You have an infinitely recursive template, just the same as e.g.

template< typename T >
int foo(){ return foo<T*>(); }

Amazingly MSVC is able to issue an error for this definition in almost no
time, "... too complex", but it insists that that is an error in <ios>...

The interesting question, too me, is whether 'mkptr' should really be
recursively instantiated, because it's never actually used.

So although the immediate problem fix is very clear, namely don't recurse
infinitely, and probably you _meant_ to write something like

Instance_base* mkptr() { return new Instance(_inst); }

the question you ask is not as clear, and I don't know the answer; however I
expect that someone will provide the answer, because it's nothing complicated,
just a matter of knowing or using the time to find the technical rule.

Btw., it's not a good idea to use an underscore at the start of a name.

Names starting with underscore followed by uppercase are reserved for the
implementation, and in practice one should regard that rule as the more
general that names staring with underscore are reserved.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Sep 19 '05 #2


try this:

struct Instance_base
{
virtual ~Instance_base() {}
virtual Instance_base* mkptr() = 0;

};
template<typename T>
struct Instance: Instance_base
{
T _inst;
Instance(const T &v): _inst(v) {}
Instance_base* mkptr() { return new Instance(_inst); }
};

Sep 19 '05 #3
You have an infinitely recursive template, just the same as e.g.

template< typename T >
int foo(){ return foo<T*>(); }

Why is it the same as above? Now, I am confused.

Sep 19 '05 #4

I thought that mkptr function wasn't generated at all (until it is
called for the first time). Is case that we have a definition of pure
virtual class that causes that function to be generated? (still don't
the infinite recursion - need to hone my metaprogramming skills :) ).
interesting question - I second it.

Sep 19 '05 #5
I see it now.

Here is an explanation (which I did already mention in passing):

Since we have an abstract class, any class that inherits from it, is
required to let the compiler know that it has overridden all of its
pure virtual functions (failing to do so is a compiler error), in which
case it starts looking for one instantiating each member function of a
template class until *Perfect* match is found. Otherwise, the subclass
is abstract by definition, and that would lead to another error.
cracker

Sep 19 '05 #6
> So although the immediate problem fix is very clear, namely don't recurse
infinitely, and probably you _meant_ to write something like

Instance_base* mkptr() { return new Instance(_inst); }
This is not what I need. These classes are part of a larger class whose
purpose is to hold any kind of value, along the lines of boost::any. Such
class is roughly defined as follows (other constructors and methods have
been intentionally omitted for clarity):

class object
{
public:
template<typename T>
object(const T &v): _inst(new instance<T>(v)) {}

object make_pointer()
{
object newobj;
newobj._inst = _inst->mkptr();
return newobj;
}

protected:
struct instance_base { .... };
template<typename T> struct instance: instance_base { ..... };

private:
instance_base* _inst;
};

Note that struct "instance" has a data member of type T and it has a
constructor that takes a value of type const T& and initializes the data
member with that value.

instance::mkptr() is used polymorphically by object::make_pointer(). The
purpose is to create a new instance of class object that contains a pointer
to the value held by the calling instance. For example:

// initializes object::_inst with an
// instance<int> containing the number 5
object x = 5;

// p should hold an instance<int*> containing
// a pointer to the value held by x
object p = x.make_pointer();

I don't know how to achieve that other than by providing that mkptr()
function.
Btw., it's not a good idea to use an underscore at the start of a name.


Yes I know that, but unfortunately this code is part of a larger project of
which I haven't control, and I was asked to change my style to match that of
the project. There's nothing more frustrating than being forced to write
programs as if you were someone else.

Marco
Sep 19 '05 #7
Sorry for using lowercase identifiers in my last reply. I had to change
naming conventions so many times that I can't even focus well on the current
one, especially after a night spent on debugging :-)

Marco
Sep 19 '05 #8
* Marco Jez:
So although the immediate problem fix is very clear, namely don't recurse
infinitely, and probably you _meant_ to write something like

Instance_base* mkptr() { return new Instance(_inst); }


This is not what I need. These classes are part of a larger class whose
purpose is to hold any kind of value, along the lines of boost::any. Such
class is roughly defined as follows (other constructors and methods have
been intentionally omitted for clarity):

class object
{
public:
template<typename T>
object(const T &v): _inst(new instance<T>(v)) {}

object make_pointer()
{
object newobj;
newobj._inst = _inst->mkptr();
return newobj;
}

protected:
struct instance_base { .... };
template<typename T> struct instance: instance_base { ..... };

private:
instance_base* _inst;
};

Note that struct "instance" has a data member of type T and it has a
constructor that takes a value of type const T& and initializes the data
member with that value.

instance::mkptr() is used polymorphically by object::make_pointer(). The
purpose is to create a new instance of class object that contains a pointer
to the value held by the calling instance. For example:

// initializes object::_inst with an
// instance<int> containing the number 5
object x = 5;

// p should hold an instance<int*> containing
// a pointer to the value held by x
object p = x.make_pointer();

I don't know how to achieve that other than by providing that mkptr()
function.


It's unclear what you're trying to achieve, and I think that _is_ the problem.

Consider that with the current design you can end up with a pointer to a
pointer to a pointer ... to a pointer to something.

Perhaps try instead to have one value class and one value pointer class, both
derived from instance_base. But whether that helps depends on the
requirements of your design. I'd start by fleshing out the requirements more
precisely -- e.g., surely you don't mean to have 'object' assignable with
all those raw pointers bandied about? And perhaps if you think of higher
level requirements you can get rid of 'object' entirely. Such classes, or use
of boost::any or similar, is nearly always an indication of a flawed design.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Sep 19 '05 #9
> Such classes, or use
of boost::any or similar, is nearly always an indication of a flawed
design.


Only if you use them to "bypass" the strong-typed nature of C++, which is
something that many people who are unfamiliar with C++ try to do. This is
not my case as I'm writing an introspection library.

Marco
Sep 19 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: MiniDisc_2k2 | last post by:
Okay I just came up with this scenario and wanted to know if it was possible. Thus, this is extremely generic code and serves no practical purpose: template <class T, class N> class A { //...
2
by: Simon White | last post by:
Hi, I have code that looks legal to me and has compiled for years and on latest VC, etc compilers. Just recently gcc made a change to their compiler (3.4) that broke it. I don't have access to...
11
by: BRG | last post by:
I know that default template arguments cannot be used in function templates but are default function parameters legal? That is, is this: ---------------------------------- #include <functional>...
5
by: ma740988 | last post by:
///// 1 Consider the _FUNCTION_ template template <typename T> int spaceOf () { int bytes = sizeof T; return bytes / 4 + bytes % 4 > 0; }
6
by: Greg Warren | last post by:
I am writing a container class so that I can reuse my double ended list code. I have a base class CListBase that handles inserts and deletes with a member function addItem, defined as:...
1
by: James Dixon | last post by:
I need to create a professional looking website I usually work in the middle tier/data tier using C#/TSQL I have looked in MSDN for some generic asp.net templates that prebuild alot of the...
9
by: Mark P | last post by:
The following code upsets one of my compilers (Sun CC). It reports that Q is not defined at line 12. It doesn't seem to like that I've renamed the template formal parameter from T to Q, because...
8
by: NVH | last post by:
I know that this question may have been asked before but I can't find it here so: If there is a class: class Foo { ... Foo (const Foo &num); // Copy constructor template <typename T> Foo...
23
by: Ben Voigt | last post by:
I have a POD type with a private destructor. There are a whole hierarchy of derived POD types, all meant to be freed using a public member function Destroy in the base class. I get warning C4624....
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.