I have three C++ files header1.h
, header2.h
, and main.cpp
. They are below:
header1.h
, which defines the function lerp
in the namespace MyNamespace
:
#ifndef HEADER_1_H
#define HEADER_1_H
namespace MyNamespace {
template <typename T>
inline float lerp(float t, T a, T b) {
return (1 - t) * a + t * b;
}
};
#endif
header2.h
, which defines a class MyClass
in MyNamespace
, which has a member function called lerp
, which calls the lerp
from header1.h
:
#ifndef HEADER_2_H
#define HEADER_2_H
#include "header1.h"
namespace MyNamespace {
struct MyClass {
float x, y, z;
void lerp(float t) {
x = lerp(t, x, 0.f);
// ^^ This results in a compiler error (no matching function for
// call to ‘MyNamespace::MyClass::lerp(float&, float&, float). Why?
// Also, either prefixing this `lerp` with MyNamespace, or changing
// the name of this member function to anything else that's not lerp,
// stops the compiler error from occurring. Why?
}
};
};
#endif
main.cpp
, which constructs an object of type MyClass
and calls MyClass::lerp()
on it:
#include "header2.h"
using namespace MyNamespace;
int main()
{
MyClass mc{1, 2, 3};
mc.lerp(4); // results in a compiler error; see the comment in "header2.h"
return 0;
}
When I try to compile main.cpp
, I receive the following compiler error about my usage of lerp
within the MyClass::lerp()
function in header2.h
:
header2.h: In member function ‘void MyNamespace::MyClass::lerp(float)’:
header2.h:12:17: error: no matching function for call to ‘MyNamespace::MyClass::lerp(float&, float&, float)’
12 | x = lerp(t, x, 0.f);
| ~~~~^~~~~~~~~~~
header2.h:11:10: note: candidate: ‘void MyNamespace::MyClass::lerp(float)’
11 | void lerp(float t) {
| ^~~~
header2.h:11:10: note: candidate expects 1 argument, 3 provided
So, my first question is, why doesn't the compiler seem to be able to find the definition of MyNamespace::lerp()
provided in header1.h
? Shouldn't it be able to find it, because we are in the same namespace (MyNamespace
) and because header2.h
includes header1.h
?
Also, I've observed that either explicitly qualifying lerp(t, x, 0.f)
with MyNamespace
, or by renaming the member function MyClass::lerp
to anything else, the compiler error goes away. Why is this?
why doesn't the compiler seem to be able to find the definition of MyNamespace::lerp() provided in header1.h?
Because when you wrote x = lerp(t, x, 0.f);
, unqualified name lookup starts and finds the member function named lerp
and so name lookup stops. Thus, the only candidate function is the member function named lerp
. And since it is incompatible with the call arguments, we get the mentioned error.
This can be seen from unqualified name lookup documentation:
For an unqualified name, that is a name that does not appear to the right of a scope resolution operator ::, name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.