Dentro da classe de modelo Bank<T>
, meu objetivo é criar uma sobrecarga para o tipo Account
de função membro void Bank<T>::makeTransfer(T, T, const double)
, de assinatura void Bank<Account>::makeTransfer(Account&, Account&, const double)
.
Ou seja, makeTransfer
a função deve aceitar parâmetros de referência quando invocada com Account
s, enquanto deve copiar os argumentos para qualquer outro tipo.
O que eu fiz foi criar outra makeTransfer<T>
função de assinatura similar, mas aceitando T&
argumentos de referência em vez de T
. Então, adicionei uma especialização de template a essa nova função usando Account
as T
.
No entanto, o MWE abaixo não compila com sucesso, veja o link do compilador GDBonline .
#include <cstdio>
#include <functional>
#include <concepts>
class Account {
public:
Account() = default;
Account(const long id, const double balance): _id{id}, _balance{balance} {
printf("Account no.%ld start balance is %f\n", _id, _balance);
}
const long getId() {
return _id;
}
const double getBalance() {
return _balance;
}
void addToBalance(const double sum) {
_balance += sum;
}
private:
long _id;
double _balance;
};
template<typename T> class Bank {
public:
void makeTransfer(T from, T to, const double amount) {
printf("ID %ld -> ID %ld: %f\n", from, to, amount);
}
void makeTransfer(T& from, T& to, const double amount) {}
};
template<> void Bank<Account>::makeTransfer(Account& from, Account& to, const double amount) {
printf("ID %ld -> ID %ld: %f\n", from.getId(), to.getId(), amount);
from.addToBalance(-amount);
to.addToBalance(amount);
printf("Account no.%ld balance is now %f\n", from.getId(), from.getBalance());
printf("Account no.%ld balance is now %f\n", to.getId(), to.getBalance());
}
int main() {
// try with fundamental type as T
Bank<long> bank;
bank.makeTransfer(1000L, 2000L, 49.95);
bank.makeTransfer(2000L, 4000L, 20.00);
// now define a bank with Account instances
Account a{500, 2600};
Account b{1000, 10'000};
Bank<Account> bank2;
bank2.makeTransfer(a, b, 49.95);
bank2.makeTransfer(b, a, 20.00);
//bank2.makeTransfer(std::ref(a), std::ref(b), 49.95);
//bank2.makeTransfer(std::ref(b), std::ref(a), 20.00);
}
O compilador protesta por não conseguir escolher a instanciação correta do modelo:
main.cpp:58:21: error: call of overloaded ‘makeTransfer(Account&, Account&, double)’ is ambiguous
58 | bank2.makeTransfer(a, b, 49.95);
| ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
main.cpp:31:8: note: candidate: ‘void Bank::makeTransfer(T, T, double) [with T = Account]’
31 | void makeTransfer(T from, T to, const double amount) {
| ^~~~~~~~~~~~
main.cpp:38:17: note: candidate: ‘void Bank::makeTransfer(T&, T&, double) [with T = Account]’
38 | template<> void Bank<Account>::makeTransfer(Account& from, Account& to, const double amount) {
| ^~~~~~~~~~~~~
Tentei injetar referências explicitamente com std::ref
, mas isso não ajudou.
Usar algo como std::same_as<T, Account>
parece redundante, pois todas as dicas para o compilador já deveriam estar disponíveis na especialização do modelo.
https://godbolt.org/z/9sEaov3K8