I read that, in simplified terms, if the C++ compiler can prove that a variable is of a certain type, it can inline virtual functions. Why can't it do it in this case (tested with MSVC 2017, clang 4.0, gcc 7.2 and icc 17):
#include <iostream>
class Callable {
public:
virtual int sq(int n) const;
};
class Square : public Callable {
public:
inline int sq(int n) const override final {
return n*n;
}
};
class Call {
public:
const Callable caller;
};
class Methods {
public:
constexpr static const Call c {Square()};
};
int main() {
using std::cout;
cout << Methods().c.caller.sq(5);
}
I noticed that clang's optimization output in godbolt (link below) says that Callable::sq
will not be inlined because its definition is unavailable. However, Methods::c
is static
and const
. Call::caller
is also const
. Also, Square::sq
is final
. As far as I know, there is no way they'll change at runtime. Or am I missing something?
On the other hand, the compiler is able to inline the function in this version:
#include <iostream>
class Callable {
public:
virtual int sq(int n) const;
};
class Square : public Callable {
public:
inline int sq(int n) const override final {
return n*n;
}
};
class Call {
public:
Callable const* caller;
};
class Methods {
public:
Call c {new Square()};
};
int main() {
using std::cout;
cout << Methods().c.caller->sq(5);
}
Why is that so? Link for godbolt for easy checking.