【问题标题】:Why is template specialization of member functions not allowed?为什么不允许成员函数的模板特化?
【发布时间】:2019-05-20 04:48:12
【问题描述】:

如果我有一些琐碎的事情,例如(澄清一下,我并不是说这是一个很好的实现,只是一个示例来演示成员函数的部分模板专业化失败):

template <typename T, typename U>
class BankAccount
{
  T money;
  U interestRate;
public:
  BankAccount(T money, U interestRate) :
    money(money), interestRate(interestRate)
  {}

  void showMeTheMoney();
};

我将能够通过以下方式专门化每个功能:

// invalid code
template <typename U>
void BankAccount <int, U>::showMeTheMoney()
{
  printf("$%d.00 interest: %f\n", money, interestRate);
}

template <typename U>
void BankAccount <long, U>::showMeTheMoney()
{
  printf("$%l.00 interest: %f\n", money, interestRate);
}

template <typename U>
void BankAccount <float, U>::showMeTheMoney()
{
  printf("$%.2f interest: %f\n", money, interestRate);
}

template <typename U>
void BankAccount <double, U>::showMeTheMoney()
{
  printf("$%.2f interest: %f\n", money, interestRate);
}

int main(int argc, char *argv[])
{
  BankAccount<double, float> b(500, 0.03);
  b.showMeTheMoney();
  BankAccount<std::uint64_t, float> c(1234, 0.01);
  c.showMeTheMoney();
}

等等。不幸的是,C++ 标准不允许这样做:

14.5.5.3.1。类模板偏特化成员的模板参数列表应与类模板偏特化的模板参数列表匹配。类模板偏特化成员的模板实参列表应与类模板偏特化的模板实参列表匹配。

因此,唯一的解决方案(据我所知)是使用类型特征或使用样板代码重现整个类。这个决定背后是否有理由,或者这在 C++ 中根本不存在,因为需求不足,还是其他原因?

【问题讨论】:

  • 除非有人提出拒绝建议来实施您所询问的内容,否则很难客观地回答为什么该功能不存在。
  • 对于它的价值,Rust 做了这样的事情,而 C++ 没有。如果您希望 C++ 做到这一点,不妨加入一个委员会。
  • 离题:将银行账户中的金额作为浮点数存储不是一个好主意
  • @MichaelChoi 使用整数类型并存储美分:stackoverflow.com/questions/149033/…
  • @MichaelChoi 它可能应该存储作为Transaction对象的序列

标签: c++ templates standards


【解决方案1】:

因为它不是您编写的成员函数的模板特化。这是班级的专业化。因此,代码应如下所示(我添加了一个公共基类,您不必为所有规范定义成员):

template <typename T, typename U>
class BankAccountBase
{
protected:
    T money;
    U interestRate;

public:
    BankAccountBase(T money, U interestRate) :
        money(money), interestRate(interestRate)
    {}
};

template <typename T, typename U>
class BankAccount
{
    T money;
    U interestRate;
public:
    BankAccount(T money, U interestRate) :
        money(money), interestRate(interestRate)
    {}

    void showMeTheMoney();
};

template <typename U>
class BankAccount <int, U> : public BankAccountBase <int, U>
{
public:
    BankAccount(int money, U interestRate) :BankAccountBase(money, interestRate) { }
    void showMeTheMoney();
};

template <typename U>
class BankAccount <long, U> : public BankAccountBase <long, U>
{
public:
    BankAccount(long money, U interestRate) :BankAccountBase(money, interestRate) { }
    void showMeTheMoney();
};
template <typename U>
class BankAccount <float, U> : public BankAccountBase <float, U>
{
    BankAccount(float money, U interestRate) :BankAccountBase(money, interestRate) { }
public:
    void showMeTheMoney();
};
template <typename U>
class BankAccount <double, U> : public BankAccountBase <double, U>
{
public:
    BankAccount(double money, U interestRate) :BankAccountBase(money, interestRate) { }
    void showMeTheMoney();
};

template <typename U>
class BankAccount <long long, U> : public BankAccountBase <long long, U>
{
public:
    BankAccount(long long money, U interestRate) :BankAccountBase(money, interestRate) { }
    void showMeTheMoney();
};


// invalid code
template <typename U>
void BankAccount <int, U>::showMeTheMoney()
{
    printf("$%d.00 interest: %f\n", money, interestRate);
}

template <typename U>
void BankAccount <long, U>::showMeTheMoney()
{
    printf("$%l.00 interest: %f\n", money, interestRate);
}

template <typename U>
void BankAccount <long long, U>::showMeTheMoney()
{
    printf("$%l.00 interest: %f\n", money, interestRate);
}

template <typename U>
void BankAccount <float, U>::showMeTheMoney()
{
    printf("$%.2f interest: %f\n", money, interestRate);
}

template <typename U>
void BankAccount <double, U>::showMeTheMoney()
{
    printf("$%.2f interest: %f\n", money, interestRate);
}

int main(int argc, char *argv[])
{
    BankAccount<double, float> b(500, 0.03);
    b.showMeTheMoney();
    BankAccount<long long, float> c(1234, 0.01);
    c.showMeTheMoney();
}

【讨论】:

    猜你喜欢
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多