我有以下内容:
#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/