vendredi 3 mars 2017

Try to use a single class variable in template class

I have the following:

 #include <iostream>
 #include <string>
 #include <utility>
 #include <type_traits>

 enum Creature { human, dog };

 template <Creature Cr, unsigned AGE=0, typename T = void>
 struct has_drive_perm {

     constexpr static bool perm = false;
 };

 template<unsigned AGE>
 struct has_drive_perm<Creature::human, AGE, typename std::enable_if<!(AGE<=17),void>::type> {

     constexpr static bool perm = true;
 };

 template <unsigned AGE>
 class Dog {

     public:
         typedef has_drive_perm<Creature::dog,AGE> tag;

         Dog(const std::string& name): name{name} {};
         static unsigned not_allowed_count;
         typename std::enable_if<!tag::perm,void>::type check_can_drive() { std::cout<<"Dogs can't drive, stupid... and so does "<<name<<". It's the "<<not_allowed_count++<<"th time you ask smth like that!"<<std::endl; }
         //typename std::enable_if<!tag::perm,void>::type check_can_drive() { std::cout<<"Dogs can't drive, stupid... and so does "<<name<<std::endl; };//std::cout<<"It's the "<<not_allowed_count++<<"th time you ask smth like that!"<<std::endl; }

     private:
         const std::string name;
 };

 template <unsigned AGE, bool B=has_drive_perm<Creature::human,AGE>::perm>//=std::enable<has_drive_perm<Creature::human,AGE>::perm>
 class Human {

     public:
         typedef has_drive_perm<Creature::human,AGE> tag;

         Human(const std::string& name): name{name} {};
         //static unsigned not_allowed_count;
         void check_can_drive() { std::cout<<"Nope, "<<name <<" does not have a licence"<<std::endl; };

     private:
         const std::string name;
 };

 template <unsigned AGE>
 class Human<AGE, true> {

     public:
         typedef has_drive_perm<Creature::human,AGE> tag;

         Human(const std::string& name): name{name} {};
         //static unsigned not_allowed_count;
         void check_can_drive() { std::cout<<"Yep, "<<name <<" has a licence"<<std::endl; };

     private:
         const std::string name;
 };

 template <unsigned AGE>
 unsigned Dog<AGE>::not_allowed_count;
 //template <unsigned AGE>
 //unsigned Human<AGE>::not_allowed_count;

 template <typename CrT>
 void check_drive_perm(CrT& creature) {

        creature.check_can_drive();
 }

 int main() {

   Dog<5> d1("John");
   Dog<10> d2("Jim");
   Human<18> h1("Marcus");
   Human<7> h2("Frank");

   d1.check_can_drive();
   d2.check_can_drive();
   h1.check_can_drive();
   h2.check_can_drive();
 }

This gives me:

Dogs can't drive, stupid... and so does John. It's the 0th time you ask smth like that!
Dogs can't drive, stupid... and so does Jim. It's the 0th time you ask smth like that!
Yep, Marcus has a licence
Nope, Frank does not have a licence

I want to use the static class variable not_allowed_count only once, so that it would count up. But as I am instantiating the dog class with two different AGE params, I get two variants of the same class (is that true? Wouldn't the compiler then complain that I have a redefinition of the class dog?). So my question is:

How is it possible to use only one static class variable not_allowed_count?

I thought of the CRTP-pattern but that only works on types and not on non-type template parameters (?)

Aucun commentaire:

Enregistrer un commentaire