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

标签 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 一次,这样它就会向上计数。但是当我用两个不同的 AGE 参数实例化 dog class 时,我得到了同一个类的两个变体(是真的吗?编译器会不会提示我是否重新定义了 dog 类?)。 所以我的问题是:

怎么可能只使用一个静态类变量 not_allowed_count?

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

最佳答案

您不能使用模板化类的静态成员来计算此类与任何模板参数的使用情况。

n3242 14.7.1/6

Each class template specialization instantiated from a template has its own copy of any static members.

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

 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; 
         }
  }

关于c++ - 尝试在模板类中使用单个类变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42574656/

相关文章:

c++ - 在显式实例化 vector<someType> 时,someType 默认构造函数用于什么?

c++ - 如果仍然可以间接执行(通过回调函数),将 C 函数声明为静态函数是不好的做法吗?

C++:如何测试编译错误以检查约束

c++ - 模板特化中 T[N] 和 T[] 的区别?

python - 在 Python/Django 中使用 Memcached - 问题

c++ - 如何将 map 中的 copy_if 复制到 vector ?

java - 使用 CreateProcess 从 Win32 C++ 应用程序启动 Java 应用程序时出错

c++ - 前向声明不适用于转换运算符

c++ - 'auto' 和显式变量声明的行为不同

c++ - 为什么标准区分直接列表初始化和复制列表初始化?