2016-11-30 163 views
1

你能告訴我爲什麼這個代碼不能編譯?編譯錯誤 - 模板,enable_if

template <typename T, T minAge, T maxAge, bool isarmed, 
typename = std::enable_if_t<std::is_arithmetic<T>::value>> 
class Citizen { 
public: 

    Citizen(T health, T age); 
    Citizen(T health, T age, T attackPower); 
    T getHealth() const { return _health; }; 
    T getAge() const { return _age; }; 
    T getAttackPower(); 
    void takeDamage(T damage); 

private: 
    T _health; 
    T _age; 
    T _attackPower; 
}; 

template <typename T, T minAge, T maxAge, bool isarmed> 
Citizen<T, minAge, maxAge, isarmed>::Citizen(T health, T age): 
     _health (health), 
     _age (age) 
{ 
    static_assert(minAge <= maxAge, "Wrong age"); 
    assert(minAge <= this->_age && this->_age <= maxAge); 
} 

我錯過了什麼?

error: invalid use of incomplete type ‘class Citizen<T, minAge, maxAge, isarmed>’ 
+0

如果我沒有弄錯,SFINAE是用於重載功能模板的解析。我不認爲你可以將它用於類模板。 –

+0

@RSahu當然可以。這是[如何'void_t'工程](http://stackoverflow.com/q/27687389/2069064) – Barry

+0

@巴里,感謝您的鏈接。對於SFINAE,我還沒有得到我的基礎知識。 –

回答

3

您聲明Citizen是一個類模板以5個模板參數:

template <typename T, T, T, bool, typename > 
class Citizen { ... }; 

,然後嘗試只用4模板參數來定義構造函數:

template <typename T, T minAge, T maxAge, bool isarmed> 
Citizen<T, minAge, maxAge, isarmed>::Citizen(T health, T age) 

沒有例如之前聲明的4模板參數Citizen,因此是錯誤。你仍然需要最後一個模板參數。


注意,這裏SFINAE沒有太大的意義,除非你有一些其他非算術Citizen類模板(這本身並沒有太大的意義)。對於T,算術類型只需要static_assert

+0

現在,如果我想爲2個場景聲明Ctor,該怎麼辦?一個isarmed ==真,相反? – tomtom

+0

第五個模板參數有一個默認類型。爲什麼編譯器不會從第一個模板參數中派生出來? –

+0

@RSahu有一個默認值。這並不意味着用戶不能提供一個不是默認的。 – Barry