I am inexperienced with C++, so I might be missing the correct search terms.
I want to replace a few library functions with my own wrappers at runtime. Basically, I would like to provide an instrumented version of the library. In an ideal world, users of the library would not have to alter their code to use this version (or, at most, change only the linking within CMakeLists.txt).
User-defined executables are often declared as follows in a CMake file.
add_library(my_code ${SOURCES})
add_dependencies(my_code ${catkin_EXPORTED_TARGETS})
target_link_libraries(my_code ${catkin_LIBRARIES})
I suppose that, to achieve this, changing target_link_libraries() would be required, so as to link to a different version.
However, even if I redefine all functions in the original header, under the same namespace, how can I refer to the original implementation?
namespace thelib {
void theFunction() {
// how do I call the original thelib::theFunction() here?
}
}
Basically it is to good practice to isolate third party dependency using come abstraction. Aim is to hide library API behind some interface, which implementation an be freely altered.
I do it more or less that:
// some header
class IDependency {
public:
virtual ~IDependency() = default;
virtual void theFunction() = 0;
};
std::unique_ptr<IDependency> depFactory(int someArg);
// some cpp
std::unique_ptr<IDependency> depFactory(int someArg)
{
if (someArg = 0) {
return std::make_unique<LibraryWrapper>();
}
if (someArg = 0) {
auto origLib = std::make_unique<LibraryWrapper>();
return std::make_unique<DepCutomization>(origLib);
}
throw std::invalid_argument("");
}
// LibraryWrapper
class LibraryWrapper : public IDependency {
public:
void theFunction() override {
::thelib::theFunction();
}
}
// DepCutomization
class DepCutomization : public IDependency {
public:
explicit DepCutomization(std::unique_ptr<IDependency> orig)
: m_orig(std::move(orig))
{}
void theFunction() override {
customAction();
m_orig->theFunction();
}
void customAction()
{}
private:
std::unique_ptr<IDependency> m_orig;
};
For cases where performance is important, I'm using static polymorphism (template programing).
Related
I have many interfaces for different listeners, the all look like this:
class ListenerA
{
public:
virtual void
onEventA(const EventA&) = 0;
};
class ListenerB
{
public:
virtual void
onEventB(const EventB&) = 0;
};
When testing, I always end up just collecting those events in a std::vector for analyzing them afterwards in a specific test suite. Those event collectors all look the same like this one for example:
class EventACollector : public ListenerA
{
public:
const auto&
events() const
{
return m_events;
}
private:
void
onEventA(const EventA& event) override
{
m_events.emplace_back(event);
}
std::vector<EventA> m_events;
};
Is there a way to template an EventTCollector, so that I do not have to write it every time? Given that the virtual function name does change for every listeners?
C++ does not have introspection, so you cannot find the virtual function in ListenerA. The other parts can go in a templated base class, but the override you'll need to define manually.
Modern C++ would use a std::function<void(EventA)> instead of a named interface, but that won't help you as a user of that old interface.
I'm struggling with a piece of code and at this point I'm questioning if what I'm trying to achieve is even possible.
Below is the code of the various DLL and the actual piece of code that's giving me an headache
First DLL:
// DLL_A
// This DLL is the main SDK which gives me the capability to create and manage extensions
class IViewportExtensionBase
{
public:
virtual ~IViewportExtensionBase();
...
};
template<typename ExtensionType>
class IViewportExtension : public IViewportExtensionBase
{
protected:
IViewportExtension()
: IViewportExtensionBase(ExtensionType::_GetName())
{ }
};
class ExtensionsManager
{
public:
static IViewportExtensionBase* GetExtension(const std::string& extensionName)
{
return _extensions[extensionName];
}
private:
std::unordered_map<std::string, IViewportExtensionBase*> _extensions;
};
Second DLL:
// DLL_B
// This is another library of the SDK which links DLL_A to add a custom capabilities to the extensions
class ViewportExtensionAdditions
{
public:
virtual ~ViewportExtensionAdditions()
{ }
virtual void CustomAddition()
{ }
};
template<typename ExtensionType>
class ICustomViewportExtension : public IViewportExtension<ExtensionType>, public ViewportExtensionAdditions
{ };
Extension DLL
// DLL_EXTENSION
// This DLL contains the actual extension which implements the interface defined by DLL_B 8of course this links DLL_B too)
class ViewportExtension_A : public ICustomViewportExtension<ViewportExtension_A>
{
public:
void CustomAddition() override;
...
}
Actual program giving me the error:
// This is a piece of code of the final program which loads the extensions and then tries to call the custom capabilities added by DLL_B
// This program knows about the headers of both DLL_A and DLL_B and links them, but it doesn't know about the headers of DLL_EXTENSION which
// is dynamically loaded by the extensions manager
auto extension = (ViewportExtensionAdditions*)ExtensionsManager::GetExtension("ViewportExtension_A");
if (extension != nullptr)
{
// This call doesn't work, meaning that is never calls the overridden method in ViewportExtension_A
// but calls some other method which looks like the virtual table is somewhat off
extension->CustomAddition();
}
I'm afraid that deriving a class injecting another (what I'm doing in DLL_B) and then casting to that other class (what I'm doing in the acqual program) is not possible.
If actually turns out it's not possible, what could be a way to achieve what I'm trying to do?
I'm trying to make platform independent code so I'm using OOP. For example, on Windows, Mac OS X, and Linux you can have windows, but on android you have views so I'm trying to abstract this.
I first made a class to represent a window or a view which I called view:
class View
{
public:
virtual ~View()
{}
virtual void display() = 0;
virtual void hide() = 0;
};
Now the problem is that on Android, there is no title for views while on Windows there are so I decided to create another class:
class NameableView : public View
{
public:
virtual void setName(const std::string& name)
};
And then finally implement the classes:
class WindowsView : public NameableView
{
/* Windows implementation */
}
class AndroidView : public View
{
/* Android implementation */
}
Then I need to make some code which sets the name for a view only if it is possible (if it inherits from the NameableView class).
So how can I solve this problem? I first thought about dynamic_cast but I often hear that having too much dynamic_cast is an indication of a design problem. I'm a beginner in C++ so maybe I didn't think the right way and I should change the whole design.
I'm trying to make platform independent code so I'm using OOP.
This is not an optimal approach - polymorphic hierarchies and virtual functions allow different concrete object types that inherit from the same interface to behave differently at run-time, but you know the platform you're going to target at compile-time.
What you should instead do is use static polymorphism and CRTP to provide a common interface that every concrete per-platform implementation must satisfy.
template <typename TDerived>
struct View
{
void display() { static_cast<TDerived&>(*this).display(); }
void hide() { static_cast<TDerived&>(*this).hide(); }
constexpr bool supportsSetView() const
{
return static_cast<TDerived&>(*this).supportsSetView();
}
};
In the case of setName, you should provide a supportsSetView check on every platform that returns true at compile-time if the view can be named. Then you perform that check on the caller side and only invoke setName if the check passes.
Example usage:
#if defined(PLATFORM_ANDROID)
struct AndroidView
{
// ...
constexpr bool supportsSetView() const { return false; }
};
using MyView = View<AndroidView>;
#else if defined(PLATFORM_WINDOWS)
struct WindowsView
{
// ...
constexpr bool supportsSetView() const { return true; }
void setName(std::string x) { /* ... */ }
};
using MyView = View<WindowsView>;
#else
#error "Unsupported platform."
#endif
Caller side:
MyView currentView;
if constexpr(currentView.supportsSetView())
{
currentView.setName("something");
}
As if constexpr(...)'s evaluation occurs at compile-time, the code will only call setName if it is supported by MyView.
I'm trying to design a library, opening only several interfaces to caller, without mess up its own internal access control. What is the proper way to do it?
For example, here is the library:
namespace ControlledLib {
class ThinkTrack1 {
friend class DeepThought;
friend class ThinkTrack2;
private:
int ResultA() { return 6; }
int ResultB() { return 5; }
};
class ThinkTrack2 {
friend class DeepThought;
private:
int ResultC() { ThinkTrack1 tt1; return tt1.ResultB() + 2; }
};
class DeepThought {
friend int DeepThoughtAnswers();
private:
int Answers() {
ThinkTrack1 tt1;
ThinkTrack2 tt2;
return tt1.ResultA() * tt2.ResultC();
}
int CreateWorld() {
return 7;
}
};
int DeepThoughtAnswers() { DeepThought dt; return dt.Answers(); }
}
, it can be called by
#include "ControlledLib.h"
int i = ControlledLib::DeepThoughtAnswers();
The actual answer is given by class DeepThought's function Answers(), however, to make only one Answers() accessible to external callers, I have to make class DeepThought's functions private, and invent a global function DeepThoughtAnswers() as an entry point, which calls class DeepThought to get the answer, then class DeepThought has to define DeepThoughtAnswers() as a friend function.
It just begins. As class DeepThought actually calls class ThinkTrack1 and class ThinkTrack2, and class ThinkTrack2 calls class ThinkTrack1 and so on... To make all these unaccessible to external caller, all these functions are set to private, and I have to define a lot of friendship. Most of all, all these messed up the internal access control!
What would be a better way to do it?
When designing an interface there are some options you can choose from. The first is to just define a C interface that exports a set of functions. These functions internally call your classes, which are hidden through this layer.
<ControlledLib.h>
extern "C" int DeepThoughAnswers();
</ControlledLib.h>
In the source file the you have the implementation for this function:
<ControlledLib.cpp>
#include "DeepThought.h"
#include "ThinkTrack1.h"
#include "ThinkTrack2.h"
int DeepThoughAnswers()
{
DeepThought dt;
return dt.Answers();
}
</ControlledLib.cpp>
The files you include in this source then use visibility without friend and you only ship the resulting library and the ControlledLib.h file.
Another way is to use C++ interface to hide the implementation details. Here comes the interface:
<ControlledLib.h>
class ControlledLib
{
public:
virtual int DeepThoughAnswers() = 0;
};
</ControlledLib.h>
Then you have an implementation of this interface, which might look like this:
<MyControlledLib.h>
class MyControlledLib : public ControlledLib
{
public:
virtual int DeepThoughAnswers();
void someOtherFunction(); //<-- not visible to the 'outside'
};
</MyControlledLib.h>
Furthermore you add a factory that allows the client to instantiate your library.
<ControlledLib.h>
#include "ControlledLib.h"
class MyControlledLibFactory
{
public:
static MyControlledLib* create();
};
</MyControlledLib.h>
To the client you only ship the factory and the interface, everything else is hidden.
So far, your interface only uses primitive types, which means you do not have to export anyting else. In case you want to use classes in your interface you need to export those for the usage, too.
<ControlledLib.h>
class ControlledLib
{
public:
virtual int DeepThoughAnswers() = 0;
virtual ComplexAnswer* DeepThoughAnswersAreComplex() = 0; //<-- ComplexAnswer header needs to be supplied too.
};
</ControlledLib.h>
I would recommend you to use more of protected keyword and reduce use of friend keywords and redesign the interface again as its looking messy. A bridge design pattern for the implement and interface will be good and you can hide the implementations as a library and distribute the interface as header files only.
I'm relatively new to the more advanced C++ features... So keep that in mind ;)
I have recently defined an Interface to some class, consisting, of course, of only pure virtual functions.
Then, I implemented a specific version of that interface in separate files.
The question is... How do I invoke the specific implementation of that Interface on the user-end side, without revealing the internals of that specific implementation?
So if I have an Interface.h header file that looks like this:
class Interface
{
public:
Interface(){};
virtual ~Interface(){};
virtual void InterfaceMethod() = 0;
}
Then, a specific Implementation.h header file that looks like this:
class Implementation : public Interface
{
public:
Implementation(){};
virtual ~Implementation(){};
void InterfaceMethod();
void ImplementationSpecificMethod();
}
Finally, under main, I have:
int main()
{
Interface *pInterface = new Implementation();
// some code
delete pInterface;
return 0;
}
How can I do something like this, without revealing the details of Implementation.h, from "main"? Isn't there a way to tell "main"... Hey, "Implementation" is just a type of "Interface"; and keep everything else in a separate library?
I know this must be a duplicate question... But I couldn't find a clear answer to this.
Thanks for the help!
You can use a factory.
Header:
struct Abstract
{
virtual void foo() = 0;
}
Abstract* create();
Source:
struct Concrete : public Abstract
{
void foo() { /* code here*/ }
}
Abstract* create()
{
return new Concrete();
}
Although the factory solution seems to fit better the OP question, a version using the PIMPL idiom can address the same issue too.
While both versions incur in an indirect call through a pointer, the PIMPL version manages to avoid the virtual interface at the expenses of being more contrived.
Header file:
class Interface
{
struct Implementation;
std::unique_ptr< Implementation > m_impl;
public:
Interface();
~Interface();
void InterfaceMethod();
};
Implementation file:
class Interface::Implementation
{
public:
void ImplementationSpecificMethod()
{
std::cout << "ImplementationSpecificMethod()\n";
}
};
Interface::Interface()
: m_impl( std::make_unique< Interface::Implementation >( ) )
{ }
Interface::~Interface() = default;
void Interface::InterfaceMethod( )
{
m_impl->ImplementationSpecificMethod();
}
Main file:
int main()
{
Interface i;
i.InterfaceMethod(); // > ImplementationSpecificMethod()
}
See it online.
You can hide some of the inner details (privates) of your Implementation class from easy view in the header file by using something like PIMPL to conceal the implementation details in the .cpp file.
See Is the pImpl idiom really used in practice? for more discussion of the pimpl idiom.