2

could you tell me why this code doesn't compile?

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

What am I missing?

error: invalid use of incomplete type ‘class Citizen<T, minAge, maxAge, isarmed>’
Barry
  • 286,269
  • 29
  • 621
  • 977
  • If I am not mistaken, SFINAE is meant be used for overload resolution of function templates. I don't think you can use it for class templates. – R Sahu Nov 30 '16 at 18:33
  • @RSahu Sure it can. That's [how `void_t` works](http://stackoverflow.com/q/27687389/2069064) – Barry Nov 30 '16 at 18:34
  • @Barry, thanks for the link. I am yet to get my basics straight regarding SFINAE. – R Sahu Nov 30 '16 at 18:46

1 Answers1

3

You declare Citizen to be a class template taking 5 template parameters:

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

and then try to define the constructor using only 4 template parameters:

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

There is no such previously declared 4-template-parameter Citizen, hence the error. You still need that last template parameter.


Note that SFINAE here doesn't make much sense unless you have some other non-arithmetic Citizen class template (which itself doesn't make much sense). Just have a static_assert for T being an arithmetic type.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • now, what if I want to declare Ctor for 2 scenarios. One for isarmed == true and the opposite? –  Nov 30 '16 at 18:41
  • There is a default type for the fifth template parameter. Why won't the compiler derive it from the first template parameter? – R Sahu Nov 30 '16 at 18:48
  • @RSahu There's a default. That doesn't mean that the user can't provide one that isn't the default. – Barry Nov 30 '16 at 18:49
  • Then, why is `Citizen::Citizen(T health, T age) ` a problem? – R Sahu Nov 30 '16 at 18:50
  • 1
    @RSahu Because `Citizen` doesn't take 4 template parameters. It takes 5. There's no template instantiation here. – Barry Nov 30 '16 at 18:59