How to count the number of CRTP subclasses of a template class?

我只是一个虾纸丫 提交于 2019-12-22 06:15:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!