问题
Does anyone know of a method to use CRTP to count the number of subclasses of an object?
Suppose we had a setup similar to the following one:
template <typename T>
class Object
{
....
};
const unsigned int ObjectSubClassCount = ...;
class Subobject : public Object<SubObject>
{
....
};
class Second : public Object<Second>
{
....
};
and so on, such that, using TMP, we might have a constant (ObjectSubClassCount
) that represents the total number of subclasses?
Does anyone know a way to do this?
Edit: I am wanting to use the result as a template parameter later on, so I need it to be done with TMP...
回答1:
Without the requirement to use the result as a template parameter later I would try it doing like this:
// Class which increments a given counter at instanciation
struct Increment {
Increment(std::size_t& counter)
{
counter++;
}
};
// This is your template base
template <typename T>
class Object
{
private:
// For every instanciation of the template (which is done for a subclass)
// the class counter should get incremented
static Increment incrementCounter;
};
// This is the global object counter
static std::size_t classCounter;
// Static Member Variable
template<typename T>
Object<T>::incrementCounter(classCounter);
Haven't tried it but should do. To have the result available as a template parameter again (MPL) I don't have enough experience in MPL but I doubt this is possible.
回答2:
Ok, so I've come upon a... somewhat acceptable answer. I figured that it would not work out if the subclasses had absolutely not knowledge of eachother (I mean, we're talking somewhat functional programming...).
Here's a solution for this. It's definitely not the solution I'd wish for; however, it is a start. I've forced all objects to use a form of CRTP, but one that uses more of a linked list format. In this way, our subclasses must be derived from an Object<> templated from:
A: itself and B: the most recent previously defined subclass
here is my code for this (I use a template from <type_traits>
once, just a note)
template <typename T> //SFINAE check for the existance of subclasscount static member
struct has_subclasscount
{
template <typename U>
static typename std::enable_if<sizeof(U::subclasscount) != 0, int>::type test(int);
template <typename U>
static char test(...);
static const bool result = (sizeof(test<T>(0)) == sizeof(int))?(true):(false);
};
template <bool res, typename T>
struct return_subclasscount //the value to return is 0 if false
{
static const int result = 0;
};
template <typename T>
struct return_subclasscount<true, T> //returns subclasscount only if the first parameter is true
{
static const int result = T::subclasscount;
};
template <typename T> //combines return_subclasscount and has_subclasscount
struct get_subclasscount
{
static const int result = return_subclasscount<has_subclasscount<T>::result, T>::result;
};
template <typename This, typename Prev>
class Object
{
public:
static const int subclasscount = 1 + get_subclasscount<Prev>::result; //the subclass count
};
class sub1 : public Object<sub1, int>
{
};
class sub2 : public Object<sub2, sub1>
{
};
class sub3 : public Object<sub3, sub2>
{
};
These last 3 empty classes are the subclasses that we're counting. This is our header file. In our main .cpp file, we have:
int main() {
std::cout << sub3::subclasscount;
char c;
std::cin >> c;
}
Running it, we get a simple output of:
3
Which confirms that it has worked. Now, some of the downsides to this solution is:
- We must know what our last defined subclass was, before we add on.
- We must keep up with anywhere we use the subclass counter, always modifying it to be from the last subclass in the list (this can be averted by using a consistant "endoflist" subclass, which would need to be maintained instead)
Upsides, though, include the fact that we do not need to upkeep any of our previously defined subclasses. However, I consider this answer more of a "starting point" than a "final solution"; perhaps something that can be expanded upon?
(also, this can easily be abused to make a form of tree structure, where subclasscount
would actually represent the depth of any given node in the tree)
Anyone have any ideas from here?
来源:https://stackoverflow.com/questions/11113702/how-to-count-the-number-of-crtp-subclasses-of-a-template-class