today i face a problem that hurts my peace of mind. I have resumed my problem in a very smart and meaningfull example where the expected result is not met although no error is generated.
#include <iostream>
namespace MATH {
template <std::size_t M, std::size_t N, class T>
class Matrix
{
};
void invert(Matrix<2, 2, double>& m)
{
std::cout << "DIM 2 : MATH version (use of the determinant)" << std::endl;
}
void invert(Matrix<3, 3, double>& m)
{
std::cout << "DIM 3 : MATH version (use of the determinant)" << std::endl;
}
}
namespace GEOM {
template <std::size_t N>
using Matrix = MATH::Matrix<N, N, double>;// orthonormal set of vectors
template <std::size_t N>
void invert(Matrix<N>& m)
{
std::cout << "DIM " << N << " : GEOM version (use of the transpose)" << std::endl;
}
void geom_foo_purpose(Matrix<3>& m)
{
invert(m);
}
}
int main(int argc, char **argv)
{
GEOM::Matrix<3> m;
GEOM::geom_foo_purpose(m);
return 0;
}
output : std::cout << "DIM 3 : MATH version (use of the determinant)" << std::endl;
In geom_foo_purpose definition, the call to invert results in an unqualified id because a template deduction is requested. So, the ADL is able to say : ok, let's look at the MATH namespace. The fact that allows MATH::invert to be prefered to the GEOM::invert version because the non template version has priority is inadmissible in this case i think.
For example, i want to develop the GEOM content first, by defining the Matrix class as a GEOM type. GEOM::invert is called. No problem. One day, i want to generalize my Matrix class in another namespace MATH and i could think : ok, i keep the same methods and i don't break the code. Just put a using MATH::Matrix... And i become unable to understand where is the performance overhead nor why some sensitive measures change.
So i actually think about three solutions :
- verify each namespaces when i add a function or when i change a using
- specify the namespace for each call
- rely on ambiguous call compiler errors, when detected
Is there a decent way to overcome this ?