🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

12 total messages Started by Brett W. Denner Thu, 05 Oct 1995 08:18
Determining between classes and built-in types
#2113
Author: Brett W. Denner
Date: Thu, 05 Oct 1995 08:18
20 lines
1132 bytes
Is there a way to identify whether a data type in a template function is a
class or a built-in type?  For example,

template <class T> void
func(T var)
{
    if ( /* test whether T is a built-in type */ )
 	/* do something based on T being a built-in type */;
    else
        /* do something else based on T being a user-define type */;A
}

Will rtti allow me to test for this?  Is there another way of determing this?

Thanks,
Brett
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Determining between classes and built-in t
#2124
Author: Steve Clamage
Date: Thu, 05 Oct 1995 18:05
40 lines
2246 bytes
In article 100000@gusak, "Brett W. Denner" <dennerbw@cliffy.lfwc.lockheed.com> writes:
>Is there a way to identify whether a data type in a template function is a
>class or a built-in type?  For example,
>
>template <class T> void
>func(T var)
>{
>    if ( /* test whether T is a built-in type */ )
> 	/* do something based on T being a built-in type */;
>    else
>        /* do something else based on T being a user-define type */;A
>}
>
>Will rtti allow me to test for this?  Is there another way of determing this?

What is the actual problem you are trying to solve? Is it really the case
that if T is a double or a char* or a FILE* you will do operation A, but if
it is a complex or a string or an fstream you will do operation B?

And what do you mean by a "user-defined type"? Consider the following:
	typedef int T1;
	typedef int (*T2)(int);
	struct T3 { double x, y; };
	typedef double T3::*T4;
I'm pretty sure you would consider T3 a user-defined type, and T1 not a
user-defined type, but T2 and T4 aren't so obvious to me.

I suspect you would be better off documenting the properties that T must
have, and write the template accordingly. If you really have two different
sets of criteria, write two templates. You can add tests to the template
that don't generate any code to verify the properties of type T. D&E has
examples of how to do that.
---
Steve Clamage, stephen.clamage@eng.sun.com



[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Determining between classes and built-in types
#2126
Author: Fergus Henderson
Date: Thu, 05 Oct 1995 18:32
65 lines
2694 bytes

"Brett W. Denner" <dennerbw@cliffy.lfwc.lockheed.com> writes:

>Is there a way to identify whether a data type in a template function is a
>class or a built-in type? 
>
>For example,
>
>template <class T> void
>func(T var)
>{
>    if ( /* test whether T is a built-in type */ )
> 	/* do something based on T being a built-in type */;
>    else
>        /* do something else based on T being a user-define type */;A
>}
>
>Will rtti allow me to test for this?  Is there another way of determing this?

The standard RTTI does not supply this information.
As recently discussed in the thread entitled
"Do we need a standard IsPointer() function?",
you can, at least in theory, use partial template specialization 
to do it yourself - although most compilers don't support this yet.

	// unless otherwise specified, a type is not builtin
	template <class T>
	inline bool is_builtin_type() { return false; }

	// all the basic types are builtin
	inline bool is_builtin_type<char>() { return true; }
	inline bool is_builtin_type<int>() { return true; }
	// etc. 

	// all pointer types are builtin
	template <class T>
	inline bool is_builtin_type<T*> () { return true; }
	template <class T>
	inline bool is_builtin_type<const T*> () { return true; }
	template <class T>
	inline bool is_builtin_type<volatile T*> () { return true; }
	template <class T>
	inline bool is_builtin_type<const volatile T*> () { return true; }

	// similarly for reference types
	// I guess you also want to handle array types
	// and pointer-to-member types

Then you can use

	if ( is_builtin_type<T>() ) ...

to test whether a type is builtin or not.

-- 
Fergus Henderson             |  "Australia is the richest country in the world,
fjh@cs.mu.oz.au              |   according to a new system of measuring wealth
http://www.cs.mu.oz.au/~fjh  |   announced by the World Bank yesterday."
PGP: finger fjh@128.250.37.3 |  - Melbourne newspaper "The Age", 18 Sept 1995.

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Determining between classes and built-in t
#2192
Author: Atman Binstock
Date: Sat, 14 Oct 1995 15:57
26 lines
1589 bytes
In article <45mor5$fms@jupiter.SJSU.EDU>,
Cay S. Horstmann <horstman@jupiter.SJSU.EDU> wrote:
>clamage@Eng.sun.com (Steve Clamage) wrote:
>
>>In article 100000@gusak, "Brett W. Denner" <dennerbw@cliffy.lfwc.lockheed.com>
> writes:
>>>Is there a way to identify whether a data type in a template function is a
>>>class or a built-in type?  For example,

How about using template specialization?
	template<class T> bool builtin() { return false; }
	template<class T> bool builtin<char>() { return true; }
	//etc
I'm not quite sure about the specialization syntax.
This does not cover pointers, though.
Is this allowed by the standard?
	template<class T> bool builtin<T*>() { return true; }
or, depending on your needs:
	template<class T> bool builtin<T*>() { return builtin<T>(); }

Atman Binstock
ajb@panix.com

[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Determining between classes and built-in t
#2217
Author: Alex Martelli
Date: Mon, 16 Oct 1995 15:04
85 lines
4183 bytes
horstman@jupiter.SJSU.EDU (Cay S. Horstmann) writes:
	...
>>>Is there a way to identify whether a data type in a template function is a
>>>class or a built-in type?  For example,
	...
>I did have this problem when trying to write a decent array template.
>For numeric and pointer types, I'd like to use memmove when the array
>grows and is relocated. For class types that cannot be done in
>general. I did "solve" the problem by having two templates, but now

Ah, so you _don't_ really care whether a certain type is built-in or
not -- what you REALLY want to know is whether an object of that type
can be moved via a simple memmove, or whether it needs the more
accurate process of "copy constructing to the new place" [presumably
via a placement new] followed by "destructing in the old place".

So, ask for _that_... have a "template<class T> bool can_memmove()"
that returns false by default, specialize it to return true for types
that CAN be moved by memmove() (all built-ins, but also several
non-built-ins, such as complex), and further allow the user of your
library to specialize it that way for _their_ own memmove'able types.

In your array class, do a "runtime" test of can_memmove() [any decent
compiler will presumably optimize away the half of your code that is
compile-time unreachable for any given instantiation of your template].

The only problem, as usual, is with _pointers_, since you cannot
specialize a template for "pointers to *anything*", alas:-(.  Now
THAT would be a neat little thing indeed to have -- a rule allowing
a template to co-exist for both "any class" AND "any pointer", with
the latter taking precedence if both versions exist and the template
is instantiated for a pointer... 

Actually, given that auto_ptr and similar "smart-pointer" templates
should be "taking over" from raw pointers in user code as time goes
by, just as useful would be the ability to specialize something like...:

--cut wishfulthinking.cc
#include <iostream.h>
#include <auto_ptr>

template<class T> inline bool isptr(const T&) { return false; }
template<class T> inline bool isptr(const T*&) { return true; }
template<class T> inline bool isptr(const auto_ptr<T>&) { return true; }

// user can add their own smartpointer templates...:
template<class T> class ptr {  // other hypothetical smartpointer template
private: T*it;
public: // pointerlike accessors/mutators to taste
};

// ...AND specialize isptr() to make it recognize them...:
template<class T> inline bool isptr(const ptr<T>&) { return true; }

int
main()
{
    int i;
    int *pi;
    auto_ptr<int> api;
    ptr<int> spi;

    cout << isptr(i) << ", "
            isptr(pi) << ", "
            isptr(api) << ", "
            isptr(spi) << endl;

    return 0;
}
--end cut

and have it emit "false, true, true, true" -- but, no matter how
desirable, I really don't see a realistic chance of this happening:-(.


Alex
--
DISCLAIMER: these are TOTALLY personal opinions and viewpoints, NOT connected
in any way with my employer, nor any other organization or individual!
Email: martelli@cadlab.it                            Phone: +39 (51) 597313
CAD.LAB s.p.a., v. Ronzani 7/29, Casalecchio, Italia   Fax: +39 (51) 597120

[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Determining between classes and built-in t
#2224
Author: David Vandevoorde
Date: Mon, 16 Oct 1995 23:41
30 lines
1833 bytes
>>>>> "AM" == Alex Martelli <martelli@cadlab.cadlab.it> writes:
[...]
AM> So, ask for _that_... have a "template<class T> bool
AM> can_memmove()" that returns false by default, specialize it to
AM> return true for types that CAN be moved by memmove() (all
AM> built-ins, but also several non-built-ins, such as complex), and
AM> further allow the user of your library to specialize it that way
AM> for _their_ own memmove'able types.

Or make an array_move<T>(...) function with suitable specializations.

[...]
AM> The only problem, as usual, is with _pointers_, since you cannot
AM> specialize a template for "pointers to *anything*", alas:-(.  Now
AM> THAT would be a neat little thing indeed to have -- a rule
AM> allowing a template to co-exist for both "any class" AND "any
AM> pointer", with the latter taking precedence if both versions exist
AM> and the template is instantiated for a pointer...

Such a rule is in the DWP (let me know if your compiler supports it,
mine doesn't :-). BTW, this is called partial specialization...

	Daveed


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Determining between classes and built-in t
#2228
Author: Ethan Henry
Date: Tue, 17 Oct 1995 16:19
64 lines
3108 bytes
In article <45ns7a$cir@panix.com> you write:
>In article <45mor5$fms@jupiter.SJSU.EDU>,
>Cay S. Horstmann <horstman@jupiter.SJSU.EDU> wrote:
>>clamage@Eng.sun.com (Steve Clamage) wrote:
>>
>>>In article 100000@gusak, "Brett W. Denner" <dennerbw@cliffy.lfwc.lockheed.co
m>
>> writes:
>>>>Is there a way to identify whether a data type in a template function is a
>>>>class or a built-in type?  For example,
>
>How about using template specialization?
>	template<class T> bool builtin() { return false; }
>	template<class T> bool builtin<char>() { return true; }

Why not use RTTI ? typeid() will tell you the info you need...

from G++ 2.7.0 typeinfo.h:

// RTTI support: typeinfo.h
// Written by Kung Hsu based upon the specification in the 20 September 1994
// C++ working paper, ANSI document X3J16/94-0158.

class type_info {
private:
  // assigning type_info is not supported.  made private.
  type_info& operator=(const type_info&);
  type_info(const type_info&);

public:
  enum node_type {
    _RTTI_BUILTIN_TYPE,               // builtin type
    _RTTI_USER_TYPE,                  // user defined type
    _RTTI_CLASS_TYPE,                 // class type
    _RTTI_POINTER_TYPE,               // pointer type
    _RTTI_ATTR_TYPE,                  // attribute type for const and volatile
    _RTTI_FUNC_TYPE,                  // function type
    _RTTI_PTMF_TYPE,                  // pointer to member function type
    _RTTI_PTMD_TYPE                   // pointer to member data type
    };

  // return node type of the object
  virtual node_type __rtti_get_node_type() const {}
<remainder deleted>

so to determine the type of object x...

if(typeid(x).__rtti_get_node_type() == _RTTI_BUILTIN_TYPE)
	cout << "x is a builtin type" << endl;
else if if(typeid(x).__rtti_get_node_type() == _RTTI_CLASS_TYPE)
	cout << "x is a class type" << endl;
etc.


Ethan
-- 
Ethan Henry                                                  ethan@learnix.ca
Instructor, Learnix Inc.                          Visit http://www.learnix.ca
 "Don't try to outweird me - I get weirder stuff than you free in my
   breakfast cereal." -Z. Beeblebrox, quoted in the Design & Evolution of C++
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Determining between classes and built-in t
#2231
Author: Fergus Henderson
Date: Tue, 17 Oct 1995 17:58
59 lines
3059 bytes
Ethan Henry <ethan@learnix.ca> writes:
>[someone wrote:]
>>>>"Brett W. Denner" <dennerbw@cliffy.lfwc.lockheed.com> writes:
>>>>>Is there a way to identify whether a data type in a template function is a

>>>>>class or a built-in type?  For example,
>>
>>How about using template specialization?
>>	template<class T> bool builtin() { return false; }
>>	template<class T> bool builtin<char>() { return true; }
>
>Why not use RTTI ? typeid() will tell you the info you need...

Perhaps because you want to write standard-conforming, portable code?

>from G++ 2.7.0 typeinfo.h:

If you are interested in writing standard-conforming portable
code, it would be more useful to read the draft standard than
to read your particular implementation's header files.

>public:
>  enum node_type {
>    _RTTI_BUILTIN_TYPE,               // builtin type
>    _RTTI_USER_TYPE,                  // user defined type
>    _RTTI_CLASS_TYPE,                 // class type
>    _RTTI_POINTER_TYPE,               // pointer type
>    _RTTI_ATTR_TYPE,                  // attribute type for const and volatile

>    _RTTI_FUNC_TYPE,                  // function type
>    _RTTI_PTMF_TYPE,                  // pointer to member function type
>    _RTTI_PTMD_TYPE                   // pointer to member data type
>    };
>
>  // return node type of the object
>  virtual node_type __rtti_get_node_type() const {}

Note that all these names (other than `node_type') are in the implementation's
namespace, since they start with two underscores or with an underscore
and a capital letter.  These names are all GNU C++ extensions.

>so to determine the type of object x...
>
>if(typeid(x).__rtti_get_node_type() == _RTTI_BUILTIN_TYPE)
>	cout << "x is a builtin type" << endl;
>else if if(typeid(x).__rtti_get_node_type() == _RTTI_CLASS_TYPE)
>	cout << "x is a class type" << endl;
>etc.

That may work with g++ 2.7, but it is not portable, and it does
not conform to the draft C++ standard.

-- 
Fergus Henderson             	WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au              	PGP: finger fjh@128.250.37.3
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Determining between classes and built-in t
#2230
Author: Alex Martelli
Date: Tue, 17 Oct 1995 20:21
77 lines
3724 bytes
vandevod@cs.rpi.edu (David Vandevoorde) writes:
	...
>AM> So, ask for _that_... have a "template<class T> bool
>AM> can_memmove()" that returns false by default, specialize it to
>AM> return true for types that CAN be moved by memmove() (all
	...
>Or make an array_move<T>(...) function with suitable specializations.

Yup, sounds quite possibly better than my off-the-cuff suggestion;
though it would make things a bit harder on the author of some new
memmove-able class (they'd have to cut-and-paste reuse some
memmove-based array_move<T> rather than just specializing the
can_memmove thingy to return true), it also opens up possibilities
for some classes that couldn't quite be handled by memmove but
might not need the full generality of placement/new loops.  The
two ideas can be combined (just a sketch, ignoring details such as
taking care of overlaps etc...):

template <class T> inline bool can_memmove(const T&) { return false; }
inline bool can_memmove(const int&) { return true; } // etc
template <class T> void array_move(T*oldar,T*newar,int numel) {
    if(can_memmove(oldar[0])) {
	memmove((void*)newar,(void*)oldar,numel*sizeof(T));
    } else {
	for(int i=0;i<numel;i++) {
	    new((void*)&newar[i]) T(oldar[i]);
	}
    }
}
void array_move(MyClass*oldar,MyClass*newar,int numel) {
    // whatever funky implementation ... :-)
}
// and a similar array_fill for default-constructing new elements
//     (perhaps a memset() to 0 for built-in types)
// and a similar array_junk for destroying elements not moved
//     (perhaps a noop for types not needing destruction)

template <class T> class ResizeableArray {
private: T* _ar; int _ne;
public: void resize(int ne) {
	    T* ar = (T*) new char[ne*sizeof(T)];
	    int overlap = min(ne,_ne);
	    array_move(_ar,ar,overlap);
	    if(ne>overlap) array_fill(ar,overlap,ne);
	    if(_ne>overlap) array_junk(_ar,overlap,_ne);
	    delete[] (char*)_ar;
	    _ar=ar; _ne=ne;
	}
        // etc...
};


>AM> THAT would be a neat little thing indeed to have -- a rule
>AM> allowing a template to co-exist for both "any class" AND "any
>AM> pointer", with the latter taking precedence if both versions exist
>AM> and the template is instantiated for a pointer...

>Such a rule is in the DWP (let me know if your compiler supports it,
>mine doesn't :-). BTW, this is called partial specialization...

Ah -- wonderful!  I had missed this novelty... chapter and verse of
the DWP please...?  No, g++ 2.7.0, the compiler I use, does not
support it yet (I did try as soon as I read this...:-).


Alex
--
DISCLAIMER: these are TOTALLY personal opinions and viewpoints, NOT connected
in any way with my employer, nor any other organization or individual!
Email: martelli@cadlab.it                            Phone: +39 (51) 597313
CAD.LAB s.p.a., v. Ronzani 7/29, Casalecchio, Italia   Fax: +39 (51) 597120

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Determining between classes and built-in t
#2238
Author: Scott Howlett
Date: Wed, 18 Oct 1995 13:37
31 lines
1810 bytes
In article <...>, martelli@cadlab.cadlab.it (Alex Martelli) wrote:

> template <class T> inline bool can_memmove(const T&) { return false; }
> inline bool can_memmove(const int&) { return true; } // etc

Perhaps this would be better as something like the following:

template<class T> class type_traits {
    enum { can_memmove = true };
};

class type_traits<foo> {
    enum { can_memmove = false };
};

etc.

That way you get the answer to can_memmove at compile time. Not only
does this save you code (both time and space) but it allows you to
do things which require compile-time constants, such as using
type_traits<T>::can_memmove as a parameter to some other template.

-- 
--
Scott Howlett
Storm Software, Inc.
howlett@netcom.com
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Determining between classes and built-in t
#2252
Author: J. Kanze
Date: Thu, 19 Oct 1995 10:46
34 lines
2428 bytes
Cay S. Horstmann (horstman@jupiter.SJSU.EDU) wrote:

|> I did have this problem [determining whether a type is built-in or
|> not] when trying to write a decent array template.
|> For numeric and pointer types, I'd like to use memmove when the array
|> grows and is relocated. For class types that cannot be done in
|> general. I did "solve" the problem by having two templates, but now
|> the risk is that someone who doesn't understand the distinction uses
|> the "BuiltinTypeArray" (not its real name) with a class type, which
|> might have bizarre results. So I think Brett's desire is not totally
|> outlandish.  

At least for your problem, I would just write the loop and forget it.

On a RISC machine, it is probably that the generated code will be
superior to using memmove, since the compiler, knowing the actual types,
can make suppositions concerning the alignment that memmove cannot.
This is also true for 68000's.

On an 80x86: the compiler will recognize the loop and generate the
optimal movs instruction in its place.  (Warning: I've not verified this
personally, but Microsoft was claiming this in adds at least 10 years
ago, so I would imagine that all compilers do it today.)  At least one
NSC 32000 compiler I used would do this too.

-- 
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
                             --Beratung in industrieller Datenverarbeitung
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Determining between classes and built-in t
#2262
Author: Scott Howlett
Date: Thu, 19 Oct 1995 21:31
47 lines
2736 bytes
Distribution:
In article <...>, kanze@gabi-soft.fr (J. Kanze) wrote:

> Cay S. Horstmann (horstman@jupiter.SJSU.EDU) wrote:
> 
> |> I did have this problem [determining whether a type is built-in or
> |> not] when trying to write a decent array template.
> |> For numeric and pointer types, I'd like to use memmove when the array
> |> grows and is relocated. For class types that cannot be done in
> |> general. I did "solve" the problem by having two templates, but now
> |> the risk is that someone who doesn't understand the distinction uses
> |> the "BuiltinTypeArray" (not its real name) with a class type, which
> |> might have bizarre results. So I think Brett's desire is not totally
> |> outlandish.  
> 
> At least for your problem, I would just write the loop and forget it.
> 

In my experience it has been beneficial to distinguish not between types
which can be shuffled around via memmove and those which cannot, but between
types which should be created with default constructors and those which
should only be created in the array with placement new.

For types which have constructors and destructors, it's usually quicker to
manage the storage for the array as an array of characters, with elements
managed by placement new and explicit destruction. For types which do not
have constructors and destructors, it's quicker to manage the array storage
directly as an array of objects of that type.

In both cases, I've found that assignment via a loop was quicker than
assignment via memmove.

The clever part is to construct the array templates so that for any type
you can just write MyArray<T> and based on info you have elsewhere provided
about T, an appropriate implementation is chosen at compile time. Through a
couple of iterations of my implementation, I've also managed to factor out
~80% of the implementation of the array into a type-independent base class.

-- 
Scott Howlett
Storm Software, Inc.
howlett@netcom.com

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads