Gostaria de ter uma sobrecarga de função em que um caso de uso passa o argumento não-matriz por ponteiro, e o outro caso de uso passa o argumento C-matriz por referência.
Infelizmente, a passagem de um argumento de matriz C seleciona ambas as funções candidatas porque o decaimento do ponteiro da matriz C deve estar no mesmo nível de consideração, tornando a situação ambígua.
#include <iostream>
static void foo(int* p) {
std::cout << "int* -> " << *p << "\n";
}
static void foo(int (&a)[4]) {
std::cout << "int[4] -> "
<< a[0] << " "
<< a[1] << " "
<< a[2] << " "
<< a[3] << "\n";
}
int main() {
int array[4]{ 10, 20, 30, 40 };
foo(array); // error: call to 'foo' is ambiguous
foo(array + 3);
}
Atualmente estou usando esta solução alternativa. Não estou satisfeito com esta solução alternativa.
static void foo(int (*a)[4]) { /*...*/ }
...que seria chamado via...
foo(&array);
A alternativa de alterar a passagem por ponteiro para passagem por referência a ponteiro void foo(int*& p)
impediria chamá-lo por, foo(array + 3)
já que é um rvalue.
Existe outra abordagem (ou modelo mágico) que poderia esclarecer as duas situações?
O contexto é preferencialmente C++17, mas se uma solução decente puder ser expressa em C++20 ou posterior, isso ainda seria interessante.
(Problema XY?) O contexto original era a passagem de argumento de um ponteiro ou array como um parâmetro de construtor de classe. O contexto original é uma tentativa de fazer um "ponteiro gordo", como o Miracle Pointer do Google, que é um substituto drop-in de ponteiro de um ponteiro bruto regular, mas contém informações de span e offset e verificações de paranoia (o que incorre em sobrecarga adicional de tempo de execução). Tentei simplificar o exemplo para o caso de reprodução saliente e mínimo.
ATUALIZAÇÃO (respondendo ao comentário): por fim, gostaria que ele também suportasse e distinguisse a const int[4]
e a const int*
também.
Despachante com
if constexpr (std::is_array
obras.ou o mesmo:
Então, você deve artificialmente piorar o construtor não array. A maneira mais simples já foi oferecida em um comentário por @user17732522. Mas se por algum motivo isso não funcionar para você, aqui vai uma abordagem mais antiga: introduza uma conversão definida pelo usuário.
Exemplo ao vivo: https://godbolt.org/z/1o9KT833x