Can modern compilers devirtualize function calls when using dependency injection - c++

Dependency injection is a very important pattern when you want your code to be testable, and it is used all the time in big C++ projects.
Here is a simple example:
// Copyright 2019 Google LLC.
// SPDX-License-Identifier: Apache-2.0
class FooInterface {
public:
virtual void f() = 0;
virtual ~FooInterface() = default;
};
class Foo : public FooInterface {
public:
void f() override { /* Actual work */ }
};
class MockFoo : public FooInterface {
public:
void f() override { /* Mock code */ }
};
class Bar {
public:
Bar(std::unique_ptr<FooInterface>&& foo) : foo_(std::move(foo)) { }
void b() { foo_->f(); }
private:
std::unique_ptr<FooInterface> foo_;
};
// In production
void production() {
auto bar = std::make_unique<Bar>(std::make_unique<Foo>());
bar->b();
// ...
}
// In tests
void test() {
auto bar = std::make_unique<Bar>(std::make_unique<MockFoo>());
bar->b();
// ...
}
One doubt that I've always had is if compilers are able to devirtualize this kind of usage of virtual functions.
I know that in the general case it's impossible to know which derived class is being used, but in the example above the compiler knows which objects are being used in the production and the test functions, because they are being explicitly instantiated.
Can modern compilers optimize this special case and remove the virtual function calls given that they know which derived class is being instantiated at compile time?
If this specific example can't be devirtualized, is there any change that can be made to it so that the calls are devirtualized?

It depends on the compiler and the particular code you are dealing with. In my experience, you should not rely on it if you really care about avoiding virtual calls.
For instance, Clang/LLVM will devirtualize your example under -O2 if f() is noexcept:
class FooInterface {
public:
virtual void f() noexcept = 0;
virtual ~FooInterface() = default;
};
But other major compilers won't. Your mileage may vary.

Related

Google mock with templates and inheritance

I am currently trying to get templates and inheritance to behave nicely with GMock. I have a feeling what I am trying to do are two opposing ideologies and I should just use an interface, but I wanted to avoid using an interface due to possible virtual call overheads (perhaps I am optimizing prematurely)
Anyway, here's an example of what I am trying to do
class ConcreteObj {
public:
// Called a lot and so don't want to hit possible virtual overhead
void performant_function();
};
class MockObj {
public:
MOCK_METHOD(void, performant_function, (), ());
};
class ITest {
public:
template<typename T>
void test_function(T& );
};
class ConcreteTest : public ITest {
public:
template<typename T>
void test_function(T& ) {};
template<>
void test_function<ConcreteObj>(ConcreteObj& obj) {
// Do something with concrete object
obj.performant_function();
}
template<>
void test_function<MockObj>(MockObj& obj) {
// Do something with mock object
}
}
What I would then like to do, is something like the following
ConcreteTest concrete_test;
ITest* test = &concrete_test;
// In production
ConcreteObj concrete_obj;
test.test_function(concrete_obj);
// In test
MockObj mock_obj;
test.test_function(mock_obj);
Which would then call ConcreteTest via the ITest interface, but the above would clearly not work without some sort of cast to the ConcreteTest as you can't have a virtual templated function.
I would be grateful if anyone has any ideas on how I could do the following, although I will probably resign myself to using a pure virtual interface and deal with the possible vtable overhead that would come if there was a IObj interface that ConcreteObj and MockObj inherited from.
To avoid runtime polymorphism, you can use template, as follow:
class ConcreteObj {
public:
// Called a lot and so don't want to hit possible virtual overhead
void performant_function();
};
class MockObj {
public:
MOCK_METHOD(void, performant_function, (), ());
};
class ITest {
public:
virtual ~ITest() = default;
virtual void test_function() = 0;
};
template <typename T>
// requires (T t){ t.performant_function(); } // C++20
class ConcreteTest : public ITest {
T t;
public:
explicit ConcreteTest(T& t) : t(t) {}
void test_function()
{
for (int i = 0; i != big_number; ++i) {
t.performant_function();
}
// ...
}
};
and then
// In production
ConcreteObj concrete_obj;
ConcreteTest<ConcreteObj> concrete_test{concrete_obj};
ITest* test = &concrete_test;
test->test_function();
// In test
MockObj mock_obj;
// EXPECT_CALL(..)
ConcreteTest<MockObj > concrete_test{mock_obj};
ITest* test = &concrete_test;
test->test_function();
If you think about the requirements you are specifying for ConcreteObj, you are asking for two things:
Absolute minimal per-call overhead of the performant_function() method.
Be able to swap-in different implementations depending on the context (i.e. when running tests vs production).
There is only one guaranteed way to get both at the same time: templates.
Your posted code doesn't provide a lot of context, so odds are that it's not going to be that simple, but it would look at lot like this:
class ConcreteTest : public ITest {
public:
template<typename T>
void test_function(T& obj) {
// Do something with obj
obj.performant_function();
};
};
// ...
ConcreteTest concrete_test;
ITest* test = &concrete_test;
// In production
ConcreteObj concrete_obj;
test->test_function(concrete_obj);
// In test
MockObj mock_obj;
test->test_function(mock_obj);
However, you ask:
(perhaps I am optimizing prematurely)
And the answer is pretty much yes. Compilers are really good at optimizing stuff. In your scenario, you could compile with -flto and use:
class IObj {
public:
virtual void performant_function() = 0;
};
class ConcreteObj final : public IObj {
public:
virtual void performant_function() = 0;
};
and that would have a solid chance of getting rid of the overhead during an optimization pass called devirtualization.

static_assert : a certain function in Derive "must" hides Base's class function

I face a strange rare problem that I want to hide a Base class's function B::f1(int).
class B{
public: void f1(int){}
public: void f1(float){}
};
class C : public B{
public: void f1(int){
//static_assert(ASSERT_that_thisFunctionHidParentFunction,"");
//some rare ugly hacky stuff
}
public: void f1(char){
//static_assert(!ASSERT_that_thisFunctionHidParentFunction,"");
}
};
Everything works fine ; I just worry about maintainability.
I wish to make sure that a function C::f1(int) always hides B::f1(int).
If B::f1(int) happen to change signature in the future (e.g. to B::f1(int,int)),
I want some compile error to notify programmers that C::f1(int) should be changed to C::f1(int,int) as well.
In real world, my problematic function f1 doesn't have overload.
But for educational purpose, I wish to know how to solve it if there are overload too. (i.e. optional)
I love a cute solution like ASSERT_that_thisFunctionHidParentFunction in my code comment.
I don't mind MACRO.
My poor solution
I tried to typedef to force compile error, but it doesn't assert-fail in some case (MCVE-coliru), because int is automatically casted to B::f1(float).
class B{
public: void f1(int,int){}
public: void f1(float){}
};
class C : public B{
public: void f1(int){
using XXX=decltype(std::declval<B>().f1(std::declval<int>()));
//static_assert(ASSERT_that_thisFunctionHidParentFunction,"");
}
public: void f1(char){
//static_assert(!ASSERT_that_thisFunctionHidParentFunction,"");
}
};
int main() {
return 0;
}
You could check that the function pointers are different.
With MSVC 2019 and Clang 8 this worked for me, however GCC rejected it as "not a constant expression", so might need something different or a a runtime assert there. Not sure which is right in regards to the standard.
class B {
public:
void f1(int) {}
void f2(int) {}
void f3(int) {}
void f1(float) {}
};
class C : public B {
public:
void f1(int) {}
void f1(char) {}
void f3(int) {}
};
static_assert(&B::f1 != &C::f1); // Won't work because of the overloading, can static_cast to get the overload you want
static_assert(static_cast<void(B:: *)(int)>(&B::f1) != static_cast<void(C:: *)(int)>(&C::f1));
static_assert(static_cast<void(B:: *)(int)>(&B::f2) != static_cast<void(C:: *)(int)>(&C::f2)); // static assertion failed
static_assert(&B::f3 != &C::f3); // passes, no static_cast as not overloaded
Be very careful with hiding a member function in this way, as the base class is public and the method is not virtual. It can easily be cast and then the derived function is not called.
C *c = ...;
B *b = c; // Implicit
b->f1(5); // Calls B::f1, not C::f1
If possible it may be best to make the inheritance protected or private to avoid accidental casting.
The way I understand your question, it seems that you want to make sure that several implementation classes comply with a certain non-virtual concept.
template <typename Candidate>
struct ShipConcept
{
constexpr ShipConcept()
{
using ProtoFoo = void (Candidate::*)(int);
(void)static_cast<ProtoFoo>(&Candidate::foo);
// Other tests ...
}
};
struct Ship_A
: private ShipConcept<Ship_A>
{
Ship_A()
{
}
void foo(int, int);
void foo(float);
void foo(int); // (1)
};
You'll get compile-time error if line (1) isn't there.

I have a C library of related functions with different prefixes. How can derived C++ classes call them without repeating code?

I am working with a driver library talking to hardware with different model numbers. The API that comes with this hardware has a different library for different major versions, even though many of the interactions are the same. For example, if I am talking to a 4000 series device, I would call
handle_t handle;
dv4000_OpenDevice(&handle);
dv4000_DoSomething(handle);
dv4000_Close(handle);
and for a 5000 series device
handle_t handle;
dv5000_OpenDevice(&handle);
dv5000_DoSomething(handle);
dv5000_Close(handle);
So now I want to create a Device base class and Device_Series4k and Device_Series5k derived classes. How can I implement this without copying most of the implementation and swapping out the function calls? Note that the API is not exactly the same for the different series, so having a make rule that generates a source file with the name substitutions at compile time won't work (although doing so with just the common parts might be feasible).
General C++ solutions with templates or macros would be ideal, but Makefile/shell tricks for Linux/gcc would work too.
EDIT
One example that works in a very limited context might be:
class Device{
public:
typedef uint16_t handle_t;
typedef int (*Opener)(handle_t*);
typedef int (*Closer)(handle_t);
Device(Opener open, Closer close) : _handle(0), _close(close)
{ open(&_handle); }
~Device(){ _close(_handle); }
private:
handle_t _handle;
Closer _close;
};
class Device_Series4k : public Device {
public:
Device_Series4k : Device(dv4000_OpenDevice, dv4000_ClosDevice) {}
};
I could do the same with templates and an additional layer of abstraction. It's still a net benefit if I want to e.g. do error checking or a bunch of common initialization/allocation type things after calling open. But it quickly becomes unbearably messy if I need to provide 20 different DoSomething signatures.
First of all, you almost certainly want a DeviceHandle class for RAII purposes:
typedef void (*CloseDeviceFn)(handle_t);
class DeviceHandle {
handle_t val;
CloseDeviceFn close;
public:
explicit DeviceHandle(handle_t v, CloseDeviceFn closeFn) noexcept : val(v), close(closeFn) {}
DeviceHandle(DeviceHandle&& rhs) noexcept : val(rhs.release()) {}
DeviceHandle& operator=(DeviceHandle&& rhs) noexcept {reset(rhs.release()); return *this;}
~DeviceHandle() noexcept {reset(nullptr);}
handle_t get() noexcept {return val;}
void reset(handle_t v) noexcept {if (val != nullptr) close(val); val = v;}
handle_t release() noexcept {handle_t t = val; val = nullptr; return t;}
};
For APIs that don't change, what you ask for is trivial:
class Device {
public:
virtual ~Device() {}; //classes with any virtual methods should have a virtual destructor
virtual void DoSomething();
};
class Device_Series4k: public Device {
DeviceHandle handle;
public:
explicit Device_Series4k(handle_t handle_)
: handle_(handle, &dv4000_Close) {
dv4000_OpenDevice(handle.get());
}
void DoSomething() {dv4000_DoSomething(handle.get());}
};
For APIs that change, then you probably have to have versioned base classes:
class DeviceApis {
public:
virtual ~Device() {};
virtual int version() = 0;
virtual void DoSomething() = 0;
};
class Device4000Apis: public Device {
public:
virtual void DoNewerConcept();
};
And then Device_Series5k would extend Device4000Apis, and you'd have to do nonsense like this:
DeviceApis myDevice = ...
Device4000Apis deviceAtLeast4000 = dynamic_cast<Device4000Apis>(myDevice);
if (deviceAtLeast4000 != nullptr) {
deviceAtLeast4000.doNewerConcept();
} else {
log.d("device doesn't support concept");
}
If you really want to avoid the copy-paste, you can fake it with templates:
template<OpenDeviceFn openDeviceFn,
CloseDeviceFn closeDeviceFn,
DoSomethingFn doSomethingFn>
class DeviceImpl: public Device {
DeviceHandle handle;
public:
explicit DeviceImpl(handle_t handle_)
: handle(handle_, closeDeviceFn) {
openDeviceFn(handle.get());
}
void DoSomething() {doSomethingFn(handle.get());}
};
typedef DeviceImpl<dv4000_OpenDevice, dv4000_Close, dv4000_DoSomething> Device_Series4k;
As demonstrated here: http://coliru.stacked-crooked.com/a/f6974f463644da50
Or another option is to make a DeviceType class that has members that are pointers to the various methods, and each Device has a pointer to the DeviceType, which would allow you to sort of emulate the template option without actually using templates, which keeps implementations out of headers, but also interferes with in-lining.

C++ idiom for base class abstract methods without dynamic dispatch overhead?

In C++, is there any way to have an "abstract" base class method (i.e., declared and callable from the base class, but implemented in subclasses) without declaring the method as virtual?
This question, of course, only applies to cases where polymorphism isn't needed (pointers/references to base types never used). Consider the following:
#define NO_OPT asm volatile (""); // to prevent some compiler optimization
template<typename DerivedType>
void doSomething(DerivedType& d) { d.foo(); }
namespace test1 {
struct Base {
inline void foo()
{
// ... do common stuff pre-call ...
foo_impl();
// ... do common stuff post-call ...
}
virtual void foo_impl() = 0; // the abstract method
};
struct D1 : public Base { virtual void foo_impl() final { NO_OPT } };
struct D2 : public Base { virtual void foo_impl() final { NO_OPT } };
// Then the usage of D1, D2, ..., DN, could be as follows:
void go() {
D1 d1; doSomething(d1);
D2 d2; doSomething(d2);
for ( long i=0; i < 5000000000; i++ ) {
// this loop takes [9] seconds
doSomething(d2);
}
}
}
Note that polymorphism is not needed in this case, and that there are plenty of optimization opportunities for the compiler.
However, I benchmarked this code in the latest g++ (4.8.2) and clang (3.4) with -O3 optimizations enabled, including link-time (LTO), and it was significantly slower than the following alternative implementation (using templates instead of virtual method):
namespace test2 {
template<typename DerivedType>
struct Base : public DerivedType // inheritance in reverse
{
inline void foo()
{
// ... do common stuff pre-call ...
DerivedType::foo_impl();
// ... do common stuff post-call ...
}
};
struct D1 { void foo_impl() { NO_OPT } };
struct D2 { void foo_impl() { NO_OPT } };
void go() {
Base<D1> d1; doSomething(d1);
Base<D2> d2; doSomething(d2);
for ( long i=0; i < 5000000000; i++ ) {
// this loop takes [3] seconds
doSomething(d2);
}
}
}
g++ and clang were remarkably consistent, each compiling optimized code that took 9 seconds to execute the test1 loop, but only 3 seconds to execute the test2 loop. So even though the test1 logic has no need for dynamic dispatch as all calls should be able to be resolved at compile time, it is still significantly slower.
So to restate my question: When polymorphism isn't needed, Is there a way to achieve this "abstract method" behavior using the convenient straight-forward class inheritance (like in test1), but without the performance penalty of virtual functions (as achieved in test2)?
Why should explicitly invoking runtime support for a situation you don't have and don't want to have be considered straightforward? That'll confuse humans, too. Templates are the perfect tool for this job.
You want a common interface. Given your example template implementation, you don't even need any obvious relation between the types that have it, just that they do have it.
The classic CRTP way is
template<class d>
struct b {
void foo() { bark(); static_cast<d*>(this)->foo_impl(); bite(); }
};
struct d1 : b<d1> { void foo_impl() { fuzzbang("d1"); } };
struct d2 : b<d2> { void foo_impl() { fizzbuzz("d2"); } };
which people will have seen before, it's idiomatic as requested, but your
class m1 { protected: void foo_impl() { f1("1"); } };
class m2 { protected: void foo_impl() { f2("2"); } };
template<class m>
struct i : private m { void foo() { bark(); m::foo_impl(); bite(); } };
has a lot to recommend it too: there's no casting necessary, and the intent is as clear.
I don't think you can legitimately compare optimizer results on code with embedded volatile accesses with results on similar code without them. Try the two implementations in your actual code. Performance for anything you're doing five billion times is almost certain to be dominated by cache effects not instruction count anyway.
If a function has a polymorphic value (a reference or pointer to a polymorphic type), and it calls a virtual function through that variable, the compiler must assume that this could be that class or any class derived from it. And since polymorphism doesn't allow the compiler to know whether there are classes derived from it, it must use a virtual dispatch to call the function.
There is only one way to avoid the use of virtual dispatch on calling a virtual function via a polymorphic value: to call the specific type's function directly, exactly as you did in your case #2.
Where you put this call is up to you. You could put the call into foo, you could have a derived_foo alternate function that people use to call the derived-class version, etc. However you want to do it, you must ultimately call the virtual function in a different way. Which requires using a different codepath.
It is possible that, if provided with a polymorphic variable of a final class, a compiler could optimize all virtual calls into that variable into non-virtual dispatches. However, that is not required behavior by the standard. Each compiler may or may not implement that optimization, so unless it becomes widespread, you can't count on it.
This question seems very much like an XY problem. You're trying to solve some problem, and you settled on a base class with a virtual function, with a derived class that you'll always be using. This problem is best solved via the CRTP, which doesn't use virtual functions at all.
If you do not need dynamic polymorphism then do not use keyword virtual in your code:
#define NO_OPT asm volatile (""); // to prevent some compiler optimization
template<typename T>
void doSomething(T& d) { d.foo(); }
namespace test1
{
struct Base
{
protected:
void prior() {}
void after() {}
};
struct D1
:public Base
{
void foo()
{
prior();
NO_OPT
after();
}
};
struct D2
:public Base
{
void foo()
{
prior();
NO_OPT
after();
}
};
void go() {
D1 d1; doSomething(d1);
D2 d2; doSomething(d2);
for ( long i=0; i < 5000000000; i++ ) {
doSomething(d2);
}
}
}

Compile time check of whether a method defined as virtual

I'm trying to come up with a way of checking in the derived class whether a method of the base class is defines as 'virtual' . Basically I would like to have the following code:
class A {
virtual void vfoo() {}
void foo() {}
virtual ~A() {}
};
class B : public A {
virtual void vfoo() {
MAGIC_CHECK(m_pA->vfoo()); // succeed
// code
m_pA->vfoo();
// code
}
virtual void foo() {
MAGIC_CHECK(m_pA->foo()); // fail compilation because foo is not virtual!
// code
m_pA->foo();
// code
}
A * m_pA;
};
The question is, how do I implement this MAGIC_CHECK?
One solution for this could be using -Woverloaded-virtual compilation flag.
Can anyone suggest a solution that will not involve this flag?
Thanks!
In C++11 it's possible to add override at the end of the function declaration in the class and it will yield a warning if the function doesn't override anything:
class B : public A {
virtual void vfoo() override { //OK
}
virtual void foo() override { //error
}
};
In C++03 standard, it's not possible to check if a method is declared as virtual or not.
You may follow,
coding standards
peer review
possibly some static analysis tool