473,385 Members | 1,732 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Automatic registration of class specialisations

edd
Hello all,

Please consider:

template<typename Tclass my_class;

template<class my_class<int>
{
//...
};

template<typename Tvoid register_type()
{
extern std::set<const std::type_info *available_types;
available_types.insert(&typeid(T));
}

I would like to know how many specialisations of my_class have been
defined in the program (and with which types). Ideally, to achieve this
I would like register_type<U>() to get called by virtue of the
existence of a my_class<Uspecialisation, for all types U.

I've thought about it for a while now and I think that this is probably
impossible, but if anyone can think of a way I'd be eternally grateful!

To give some more context: I'm wanting to implement a small
unit-testing framework where each test-fixture is a specialisation of a
fixture<template class e.g.

template<typename test_t, int test_idclass fixture;

enum test_ids
{
equality,
comparison,
serialisation,
//...
}

template<class fixture<gadget, equality>
{
public:
fixture() { /* set up */ }
~fixture() { /* tear down */ }
void run_tests() { /* ... */ }
};

template<class fixture<gadget, serialisation>
{
//...
};

This would allow me to index/iterate-over tests by class and test-id.
Given this final goal, someone may be able to spot another way to do
what I'm aming for...?

Regards,

Edd

Aug 12 '06 #1
5 1839
ed*@nunswithguns.net wrote:
Please consider:

template<typename Tclass my_class;

template<class my_class<int>
{
//...
};

template<typename Tvoid register_type()
{
extern std::set<const std::type_info *available_types;
available_types.insert(&typeid(T));
}

I would like to know how many specialisations of my_class have been
defined in the program (and with which types). Ideally, to achieve this
I would like register_type<U>() to get called by virtue of the
existence of a my_class<Uspecialisation, for all types U.

I've thought about it for a while now and I think that this is probably
impossible, but if anyone can think of a way I'd be eternally grateful!
You're trying to inherit behavior without specifying the inheritance
relationship in the specializations. You can't do that automatically.
If you forced all specializations to inherit from a common base class
(perhaps using some template metaprogramming tricks to make sure the
creator of the specializations didn't forget to inherit from the base
class), you could do the registering in its constructor. Something
like:

struct test_base
{
typedef std::set<const std::type_info*my_set;
static my_set available_types_;

test_base( const std::type_info* const ti )
{
const pair<my_set::iterator, boolresult
= available_types_.insert( ti );
assert( result.second );
}

virtual ~test_base() {}
};

template<class Tstruct my_class;

template<struct my_class<int: test_base
{
my_class() : test_base( &typeid(*this) ) {}
// ...
};

Then, where you iterate over the types, you could do a compile-time
assertion on std::tr1::type_traits::is_base_of<test_base, T>::value
(which is the same as Boost's type_traits) or on Loki's SUPERSUBCLASS
(see http://sourceforge.net/projects/loki-lib/).

Not ideal, but it seems like an ok workaround.

Cheers! --M

Aug 12 '06 #2
edd
Hi there,

mlimber wrote:
You're trying to inherit behavior without specifying the inheritance
relationship in the specializations. You can't do that automatically.
If you forced all specializations to inherit from a common base class
(perhaps using some template metaprogramming tricks to make sure the
creator of the specializations didn't forget to inherit from the base
class), you could do the registering in its constructor. Something
like:

struct test_base
{
typedef std::set<const std::type_info*my_set;
static my_set available_types_;

test_base( const std::type_info* const ti )
{
const pair<my_set::iterator, boolresult
= available_types_.insert( ti );
assert( result.second );
}

virtual ~test_base() {}
};

template<class Tstruct my_class;

template<struct my_class<int: test_base
{
my_class() : test_base( &typeid(*this) ) {}
// ...
};
I already have a couple of iterations comparable to what you suggest
here. I may have to settle for this but unfortunately it's not really
what I want. The above system would only become aware of each
specialisation when instances are created (manually by the tester),
where as what I'd really like is the system to be aware of the
specialisations merely by the existence of their definitions -- by the
T-specialisation definition triggering a call to register_fixture<T>(),
for example. That way only the fixtures that are requested/queued by
the tester may be created and run.

So doing it as above would mean calling a constructor for each
specialisation manually, instead of calling register_fixture<T>()
manually, for each T. I think the latter is still preferable since the
fixtures wouldn't have to be set-up to be registered.

Nevertheless, your comments seem to confirm that there probably is no
way to do exactly what I want, which in it's own way is helpful --
thanks.

Edd

Aug 13 '06 #3
ed*@nunswithguns.net wrote:
Hello all,

Please consider:

template<typename Tclass my_class;

template<class my_class<int>
{
//...
};

template<typename Tvoid register_type()
{
extern std::set<const std::type_info *available_types;
available_types.insert(&typeid(T));
}

I would like to know how many specialisations of my_class have been
defined in the program (and with which types). Ideally, to achieve this
I would like register_type<U>() to get called by virtue of the
existence of a my_class<Uspecialisation, for all types U.
How many methods and static data members of the my_class class template
have to be instantiated in order to qualify as a my_class
"specialiazation"? Remember that (unless explicitly instantiated) the
methods and static data members of a template class are instantiated on
an individual basis. Each one being instantiated only when needed.
I've thought about it for a while now and I think that this is probably
impossible, but if anyone can think of a way I'd be eternally grateful!
First it is neccessary to decide exactly what to count - before
concluding that it is not possible to count whatever is to be counted.
And given that there can only be a finite number of instantiations of a
class template - it should be possible to count each one.

As an example, assume that the program wishes to count number of
unique, parameterized types used to construct a UnitTest class
template. One possible solution would look like the following:

struct Fixture
{
template <class T>
Fixture(const T* t)
{
static int didRegisterType;

if (didRegisterType == false)
{
++sNumFixtureTypes;
RegisterFixture( typeid(T)); }
}
}
static int sNumFixtureTypes;
...
};

int Fixture:: sNumFixtureTypes = 0;

template <class T>
struct UnitTest : public Fixture
{
UnitTest() : Fixture(static_cast<T*>(NULL)) {}
};

Here Fixture's static data member sNumFixtureTypes counts the number of
unique types used to construct UnitTest objects (which may be equal to
- or less than - the number of UnitTest objects constructed).
To give some more context: I'm wanting to implement a small
unit-testing framework where each test-fixture is a specialisation of a
fixture<template class e.g.

template<typename test_t, int test_idclass fixture;

enum test_ids
{
equality,
comparison,
serialisation,
//...
}

template<class fixture<gadget, equality>
{
public:
fixture() { /* set up */ }
~fixture() { /* tear down */ }
void run_tests() { /* ... */ }
};

template<class fixture<gadget, serialisation>
{
//...
};

This would allow me to index/iterate-over tests by class and test-id.
Given this final goal, someone may be able to spot another way to do
what I'm aming for...?
Having clients specialize an entire template class for each and every
type is likely to prove as error-prone as it is tedious. Worse, there
is no constraint on the client's specialization - the resulting class
may not even be usuable as a unit test.

A much better idea would be to have clients specialize a single method
of the UnitTest class template - instead of the entire class template.
For example, clients could specialize just the RunTests() method for a
particular type. In fact, declaring RunTests an abstract method in the
Fixture base would force any client instantiating a UnitTest for a type
to specialize the RunTests method:

struct Fixture
{
template <class T>
Fixture(const T* t) { RegisterFixture( typeid(T)); }

virtual void RunTests() = 0;
};

int Fixture::sFixtureCount = 0;

template <class T>
struct UnitTest : public Fixture
{
UnitTest() : Fixture(static_cast<T*>(NULL)) {}

void RunTests();
...
}

Now the client can explicitly instantiate a UnitTest for a particular
type;

class Gadget {};

// instantiate entire UnitTest template class for Gadget
template class UnitTest<Gadget>;

which in turn forces the client to specialize its RunTests() method:

void UnitTest<Gadget>::RunTests()
{
// implement Gadget tests

}

Greg

Aug 13 '06 #4
edd
Hi Greg, thanks for your response.

Greg wrote:
ed*@nunswithguns.net wrote:
Hello all,

Please consider:

template<typename Tclass my_class;

template<class my_class<int>
{
//...
};

template<typename Tvoid register_type()
{
extern std::set<const std::type_info *available_types;
available_types.insert(&typeid(T));
}

I would like to know how many specialisations of my_class have been
defined in the program (and with which types). Ideally, to achieve this
I would like register_type<U>() to get called by virtue of the
existence of a my_class<Uspecialisation, for all types U.

How many methods and static data members of the my_class class template
have to be instantiated in order to qualify as a my_class
"specialiazation"? Remember that (unless explicitly instantiated) the
methods and static data members of a template class are instantiated on
an individual basis. Each one being instantiated only when needed.
Ah yes, good point. Well, the run_tests() member function of a
specialization is what matters. The user can choose to give
ctor/dtor/extras to facilitate the tests, but they're not required to
do so if they're not needed.
First it is neccessary to decide exactly what to count - before
concluding that it is not possible to count whatever is to be counted.
And given that there can only be a finite number of instantiations of a
class template - it should be possible to count each one.
Indeed. But it's not instantiations I want to count. It's the number of
specialization definitions I'm after, or rather all the types for which
a particular template class is specialized in code. I'm not sure that
I've comminucated this very well up until now.
As an example, assume that the program wishes to count number of
unique, parameterized types used to construct a UnitTest class
template. One possible solution would look like the following:

struct Fixture
{
template <class T>
Fixture(const T* t)
{
static int didRegisterType;

if (didRegisterType == false)
{
++sNumFixtureTypes;
RegisterFixture( typeid(T)); }
}
}
static int sNumFixtureTypes;
...
};

int Fixture:: sNumFixtureTypes = 0;

template <class T>
struct UnitTest : public Fixture
{
UnitTest() : Fixture(static_cast<T*>(NULL)) {}
};

Here Fixture's static data member sNumFixtureTypes counts the number of
unique types used to construct UnitTest objects (which may be equal to
- or less than - the number of UnitTest objects constructed).
Ok. But again, I don't know if you realise that this isn't really what
I'm aiming for. I'll be more specific about this in a bit...
To give some more context: I'm wanting to implement a small
unit-testing framework where each test-fixture is a specialisation of a
fixture<template class e.g.

template<typename test_t, int test_idclass fixture;

template<class fixture<gadget, equality>
{
public:
fixture() { /* set up */ }
~fixture() { /* tear down */ }
void run_tests() { /* ... */ }
};
Having clients specialize an entire template class for each and every
type is likely to prove as error-prone as it is tedious. Worse, there
is no constraint on the client's specialization - the resulting class
may not even be usuable as a unit test.
I'm not sure I agree with this. All the work the user has to do to
construct a basic fixture would be the following, in an ideal world.

template<struct fixture<vec3D>
{
void run_tests()
{
vec3D u, v; // or as members, initialized in the ctor
ensure("default equality", u == v);
ensure_not("default inequality", u != v);
}
};

If by virtue of the above definition existing in code, I could have the
register_fixture<vec3D>() function called, then the specialization
would be registered with the system. Something like:

struct fixture_runner_base
{
virtual ~fixture_runner_base() { }
virtual void run_tests() = 0;
};

template<typename test_t>
struct fixture_runner : fixture_runner_base
{
void run_tests()
{
// exception catching machinery etc omitted
fixture<test_tf;
f.run_tests();
}
};

template<typename test_t>
void register_fixture()
{
shared_ptr p(new fixture_runner<test_t>);
tell_system_about_fixture(typeid(test_t), p);
}

Now all the fixture-types would have been registered automatically
(again, in an ideal world) and I can provide iterators to let a tester
select which tests to use at run time (perhaps through a GUI or
whatever). No fixture has been instantiated yet, and none will until
the tester calls the fixture_runner_base::run_tests() through their
custom-vetted iterators.
A much better idea would be to have clients specialize a single method
of the UnitTest class template - instead of the entire class template.
For example, clients could specialize just the RunTests() method for a
particular type. In fact, declaring RunTests an abstract method in the
Fixture base would force any client instantiating a UnitTest for a type
to specialize the RunTests method:

struct Fixture
{
template <class T>
Fixture(const T* t) { RegisterFixture( typeid(T)); }

virtual void RunTests() = 0;
};

int Fixture::sFixtureCount = 0;

template <class T>
struct UnitTest : public Fixture
{
UnitTest() : Fixture(static_cast<T*>(NULL)) {}

void RunTests();
...
}

Now the client can explicitly instantiate a UnitTest for a particular
type;

class Gadget {};

// instantiate entire UnitTest template class for Gadget
template class UnitTest<Gadget>;

which in turn forces the client to specialize its RunTests() method:

void UnitTest<Gadget>::RunTests()
{
// implement Gadget tests

}
I can see that would work fine. Indeed it's an alternative that I've
considered, but I feel that the above is actually more error prone that
what I have currently; the user must remember to derive from Fixture
and call it's constructor with the somewhat obscure cast as it's
argument.

If they forget to over-ride RunTests() they'll get a compiler error
something like "can't instantiate MyUnitTest because RunTests() is
abstract", as opposed to "No such member function
fixture<vec3D>::run_tests()". I don't think either is better than the
other -- they're both enough of a clue for the user to guess what's
gone wrong.

Regardless of which is 'best', I still don't have the registration
function called until an instantiation is made, rather than just by
virtue of some kind of definition in code.

I hope that I've understood what you're saying and that I've clarified
my aims if they were unclear before.

Edd

Aug 13 '06 #5
edd
Gosh, I've just realised that I mis-understood your code. I'll give it
some more thought, now.
My apologies.

Edd

Aug 13 '06 #6

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

Similar topics

12
by: Tim Clacy | last post by:
Your expertise will be appreciated... Here's a general templatised class; all specialisations of this class should have a pointer to a specialisation of the same, templatised type: ...
7
by: Lionel B | last post by:
Greetings. The following code compiles ok and does what I'd expect it to do: ---------- START CODE ---------- // test.cpp
0
by: Sunil Menon | last post by:
Dear All, Can we automatically register ActiveX controls on aspx pages? I know that winform controls don't need registration, but they require CLR & .Net runtime installed on the client...
1
by: Raventhorn | last post by:
I am trying, as I can see many are, to avoid the CreateUserWizard's CreateUser step from creating the user until I am ready to do it. I have a rather complex registration because I have various...
1
by: delusion7 | last post by:
Trying to create a table and insert records from a webform and I keep getting this message: "Successfully created the registration table. Unable to execute the query. Error code...
9
by: Bit Byte | last post by:
Can't seem to get my head around the point of a trait class - no matter how many times I read up on it - why not simply use functors or function pointers ? Anyone care to explain this in a...
9
by: andrewfelch | last post by:
Hello all, I'm using the metaclass trick for automatic reloading of class member functions, found at: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/160164 My problem is that if I 1)...
16
by: PengYu.UT | last post by:
Hi, I want to partial specialize the member function doit. But it doesn't work. Could you please help me to figure out what is wrong? Thanks, Peng template <typename T> class A {
4
by: Greg Ewing | last post by:
I'm creating a COM server in Python that will have one main class, with methods that create and return instances of other classes. I've found that I need to use win32com.server.util.wrap and...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
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
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.