Consider the following code with a template method design pattern:
class A {
public:
void templateMethod() {
doSomething();
}
private:
virtual void doSomething() {
std::cout << “42\n”;
}
};
class B : public A {
private:
void doSomething() override {
std::cout << “43\n”;
}
};
int main() {
// case 1
A a; // value semantics
a.templateMethod(); // knows at compile time that A::doSomething() must be called
// case 2
B b; // value semantics
b.templateMethod(); // knows at compile time that B::doSomething() must be called
// case 3
A& a_or_b_ref = runtime_condition() ? a : b; // ref semantics
a_or_b_ref.templateMethod(); // does not know which doSomething() at compile time, a virtual call is needed
return 0;
}
I am wondering if the compiler is able to inline/unvirtualize the “doSomething()” member function in case 1 and 2. This is possible if it creates 3 different pieces of binary code for templateMethod(): one with no inline, and 2 with either A::doSomething() or B::doSomething() inlined (that must be called respectively in cases 3, 1 and 2)
Do you know if this optimization is required by the standard, or else if any compiler implements it ? I know that I can achive the same kind of effect with a CRT pattern and no virtual, but the intent will be less clear.
The standard does not require optimisations in general (occasionally it goes out of its way to allow them); it specifies the outcome and it is up to the compiler to figure out how best to achieve it.
In all three cases I would expect templateMethod
to be inlined. The compiler is then free to perform further optimisations; in the first two cases it knows the dynamic type of this
and so can generate a non-virtual call for doSomething
. (I'd then expect it to inline those calls.)
Have a look at the generated code and see for yourself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With