A versão variádica sobrecarregada de uma função deve ter a menor prioridade, quando o compilador escolhe uma especialização de modelo. No entanto, esse não é o caso quando um argumento de função precisa ser convertido para uma classe base antes de corresponder a um argumento de modelo. Veja o exemplo abaixo.
class A {};
class B : public A {};
template<class... Args>
void foo(Args&&... argsPack) {
std::cout << "variadic function called" << std::endl;
}
void foo(A&) {
std::cout << "non-variadic function called" << std::endl;
}
int main() {
foo("Hello");
B b;
foo(b);
}
A saída deste programa resulta em
variadic function called
variadic function called
Se eu quisesse que a função não-variádica fosse chamada, eu teria que deletar a função sobrecarregada variádica inteiramente. Ou alternativamente eu teria que escrever uma terceira função sobrecarregada que aceitasse instâncias da classe B diretamente:
void foo(B&) {
std::cout << "non-variadic function called" << std::endl;
}
No entanto, quero evitar ambas as soluções, porque elas não são elegantes e propensas a erros para meu projeto. Então, há uma terceira solução para isso?
Você pode restringir seu template. Eu adiciono sobrecarga extra para simplificar o requisito:
Demonstração
Você pode atingir seu objetivo criando modelos de ambas as versões com referências universais e habilitando somente a versão não variável se o argumento derivar de A.
Demonstração: https://godbolt.org/z/jqjvcbKfP