|
Boost : |
From: Jaakko Jarvi (jajarvi_at_[hidden])
Date: 2001-11-20 12:01:16
Hi,
I needed to find out whether a given type was a stream or not.
The is_convertible template wasn't useful, as the stream could be
any instantiation of basic_stream. I just needed to know whether the type
was any instantiation of a basic_stream, or derived from any instantiation
of a basic_stream.
I wrote some traits classes for this purpose. They reside in
boost/lambda/detail/is_instance_of.hpp in lambda_development branch,
but I think a better place for those classes would be the type_traits
library - if they're considered to be generally useful.
The usage is as:
is_instance_of_2<std::istream, basic_stream>::value // true
is_instance_of_2<int, basic_stream>::value // false
There are separate templates (is_instance_of_1, is_instance_of_2, ...)
for different numbers of template parameters of the second argument.
As a side note, this seems to be a case of template template parameter
use, where the same effect cannot be achieved with other language
constructs.
Below is the implementation and a small test program (compiles with gcc
and KCC, gcc requires some tricks like with is_convertible)
Cheers, Jaakko
-- Jaakko Järvi, jajarvi_at_[hidden]
// -------------------------------------------------------------------
// -------------------------------------------------------------------
// is_instance_of --------------------------------
//
// is_instance_of_n<A, B>::value is true, if type A is
// an instantiation of a template B, or A derives from an instantiation
// of template B
// //
//
// n is the number of template arguments for B
//
// Example:
// is_instance_of_2<std::istream, basic_stream>::value == true
#include <iostream>
typedef char yes_type;
typedef double no_type;
#ifndef __GNUC__
// store a pointer, as passing non-PODs through ellipsis results in
// warnings in some compilers
template <class From, template <class> class To>
struct is_instance_of_1
{
private:
static no_type _m_check(...);
template <class T1>
static yes_type _m_check(const To<T1>*);
static From* _m_from;
public:
static const bool value = sizeof( _m_check(_m_from) ) ==
sizeof(yes_type);
void foo();
};
template <class From, template <class, class> class To>
struct is_instance_of_2
{
private:
static no_type _m_check(...);
template <class T1, class T2>
static yes_type _m_check(const To<T1, T2>*);
static From* _m_from;
public:
static const bool value = sizeof( _m_check(_m_from) ) ==
sizeof(yes_type);
void foo();
};
#else
// GCC version
template <class From, template <class> class To>
struct is_instance_of_1
{
private:
static no_type _m_check(...);
template <class T1>
static yes_type _m_check(const To<T1>*);
static From* _m_from;
public:
static const bool value;
void foo();
};
template <class From, template <class> class To>
const bool
is_instance_of_1<From, To>::value
= sizeof( _m_check(_m_from) ) == sizeof(yes_type);
template <class From, template <class, class> class To>
struct is_instance_of_2
{
private:
static no_type _m_check(...);
template <class T1, class T2>
static yes_type _m_check(const To<T1, T2>*);
static From* _m_from;
public:
static const bool value;
void foo();
};
template <class From, template <class, class> class To>
const bool
is_instance_of_2<From, To>::value
= sizeof( _m_check(_m_from) ) == sizeof(yes_type);
#endif
template <class T1> struct A1 {};
template <class T1, class T2> struct A2 {};
class B1 : public A1<int> {};
class B2 : public A2<int,int> {};
// classes that are convertible to classes that derive from A instances
// This is not enough to make the test succeed
class C1 { public: operator A1<int>() { return A1<int>(); } };
class C2 { public: operator B2() { return B2(); } };
int main() {
using std::cout;
cout << is_instance_of_1<B1, A1>::value; // true
cout << is_instance_of_1<A1<float>, A1>::value;// true
cout << is_instance_of_1<int, A1>::value;// false
cout << is_instance_of_1<C1, A1>::value;// false
cout << is_instance_of_2<B2, A2>::value;// true
cout << is_instance_of_2<A2<int, float>, A2>::value;// true
cout << is_instance_of_2<int, A2>::value;// false
cout << is_instance_of_2<C2, A2>::value;// false
cout << "\n";
return 0;
}
// -------------------------------------------------------------------
// -------------------------------------------------------------------
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk