尝试在模板类中使用单个类变量

时间:2017-03-03 09:06:40

标签: c++ c++11 templates

我有以下内容:

#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 <typename CrT>
void check_drive_perm(CrT& creature);

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;
        friend void check_drive_perm<Dog<AGE>>(Dog<AGE>&);

    private:
        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; }
        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;
        friend void check_drive_perm<Human<AGE,B>>(Human<AGE,B>&);

    private:
        void check_can_drive() { std::cout<<"Nope, "<<name <<" does not have a licence"<<std::endl; };
        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;
        friend void check_drive_perm<Human<AGE,true>>(Human<AGE,true>&);

    private:
        void check_can_drive() { std::cout<<"Yep, "<<name <<" has a licence"<<std::endl; };
        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");

    check_drive_perm(d1);
    check_drive_perm(d2);
    check_drive_perm(h1);
    check_drive_perm(h2);
}

这给了我:

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

我只想使用静态类变量not_allowed_count一次,以便它会计数。但是当我用两个不同的dog class参数实例化AGE时,我得到同一类的两个变体(是真的吗?编译器然后会抱怨我重新定义了班级狗?)。 所以我的问题是:

如何只使用一个静态类变量not_allowed_count?

我想到了CRTP模式,但这只适用于类型,而不适用于非类型模板参数(?)

1 个答案:

答案 0 :(得分:1)

您不能使用模板化类的静态成员来计算具有任何模板参数的此类的用法。

n3242 14.7.1 / 6

  

从模板实例化的每个类模板特化都有   它自己的任何静态成员的副本。

如果你想使用静态变量,你可以使用继承,例如。

 class not_allowed_counter
 {
 public:
    static unsigned not_allowed_count;
 };

 unsigned not_allowed_counter::not_allowed_count;

 template <unsigned AGE>
 class Dog : public not_allowed_counter {
    //
         typename std::enable_if<!tag::perm,void>::type check_can_drive() 
         {
            const unsigned not_allowed_count = static_cast<not_allowed_counter*>(this)->not_allowed_count++;
            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; 
         }
  }