I am trying to define a common interface to a set of functions and classes that will have multiple different backend implementations (Using different libraries).
As such I'd really rather, simply, define a function in one place and not in each separate namespace.
For example, I have a global function:
extern void Func();
Now I want to have 3 separate implementations of that function. One would be a straight C, One would be a hand coded assembler and one would be using library 'x'.
I am effectively trying to avoid doing the following:
namespace C
{
extern void Func();
}
namespace Asm
{
extern void Func();
}
namespace LibX
{
extern void Func();
}
Is there a good pattern to avoid doing this? When there are 100 odd functions it will become much more of a pain.
The only idea I can think of is to move all the definitions into a header file that has no header guards and then doing:
namespace C
{
#include "Functions.h"
}
namespace Asm
{
#include "Functions.h"
}
namespace LibX
{
#include "Functions.h"
}
Is there a better way of doing this that anyone can think of?
Make it a virtual function in an abstract base class. Implement it whenever you feel like it in a derived class.
class Foo{
public:
virtual void bar() const=0;
}
class FooASM:public Foo{
public:
virtual void bar() const{ ... }
}
etc.
I guess you want static polymorphism - means a template or a macro:
Template:
#include "C_Functions.h"
#include "Asm_Functions.h"
#include "LibX_Functions.h"
enum Namespace
{
NamespaceC,
NamespaceAsm,
NamespaceLibX
}
template <Namespace> Func();
template <> inline Func<NamespaceC>() { return C_Func(); }
template <> inline Func<NamespaceAsm>() { return Asm_Func(); }
template <> inline Func<NamespaceLibX>() { return LibX_Func(); }
const Namespace NSpace = ...
inline void f() {
Func<NSpace>()
}
An advantage is: You may have a common implementation for a specific function.
Similar you may do with macros (or you combine it)
I fear it ends up in #ifdef ... anyway, unless you try to have one lib for any hardware/system (which is pointless, in my view).
Related
Suppose I have a class Foo like this:
foo.h:
namespace mine {
class Foo {
Widget widget_;
public:
void bar();
// some other members...
};
} // namespace mine
foo.cpp:
#include "foo.h"
namespace mine {
void Foo::bar() {
// Some very long code
}
} // namespace mine
where I want to split bar() into multiple functions for readability reasons. The functions themselves don't have any particular meaning to Foo (or any other entity than Foo::bar()) and are only used to split up bar(), so according to this discussion I would do the following in the source file:
foo.cpp (refactored):
#include "foo.h"
// anonymous namespace to put all helper functions
namespace {
void computeResult() { ... }
void modifyWidget(Widget& w) { ... }
void doThis() { ... }
void doThat(Widget& w) {
// ...
modifyWidget(w);
}
} // <anonymous> namespace
// actual methods are defined here
namespace mine {
void Foo::bar() {
::doThis();
::doThat(widget_);
::computeResult();
}
} // namespace mine
So I am defining an anonymous namespace in the source file in order to define the helper functions, such that I have static linkage and the helper functions are not visible from outside the source file. One thing that looks odd to me is that class methods depend on functions that are not part of the class, but then we would not be able to use even the standard library if this was an issue.
Is this approach sensible? Do you have better suggestions?
Is there a problem with passing the private member Foo::widget_ to some freestanding function that modifies it (doThat())? I'm assuming here that in the narrow context of a static linkage helper function, the callers/callees know what they are doing.
Yes, it's sensible. It's also not uncommon, and it's my impression that it's gaining popularity.
Linkage has no effect whatsoever on how functions work, and a private member variable works exactly like all other variables (except you can't access its name from the outside).
That is, it's exactly like passing any variable to any function.
Currently I am writing a class that supports data proccessing on the cpu or gpu utilizing preprocessor definitions to determine which header file to include.
IE
#ifdef CPU_work
#include "cpu_backend.h"
#endif
#ifdef GPU_work
#include "gpu_backend.h"
#endif
class Work {
//Implementation dependant upon included header
}
However, there maybe instances where I would need both variants. Is there anyway I could do something like....
namespace CPU {
#define CPU_work
//Generate implementation of WorkClass with cpu_backend.h
}
namespace GPU {
#define GPU_work
//Generate implementation of WorkClass with gpu_backend.h
}
and therefor determine which implementation I want via something like...
CPU::Work cpuObject;
GPU::Work gpuObject;
Would be happy with any work-arounds also.
Much thanks JJ.
This might be the place to use a template method design. Your base class implements everything that is common to both CPU and GPU and then you use abstract functions where there are differences.
class Work {
public:
void execute() {
// Do some initializing
foo();
// Do some middle stuff
bar();
// Do some final stuff
}
private:
virtual void foo() = 0;
virtual void bar() = 0;
}
class CpuWork: public Work {
virtual void foo() {
// Do some CPU stuff
}
virtual void bar() {
// Do some more CPU stuff
}
}
class GpuWork: public Work {
virtual void foo() {
// Do some GPU stuff
}
virtual void bar() {
// Do some more GPU stuff
}
}
You now can't use your base class Work by accident since it's abstract and you can't accidentally invoke your derived classes foo or bar since they are private members of the base class.
Interesting question:) If I understood your goals correct, I can suggest a few solutions.
First uses template specialization, template default arguments and (of course) some macros.
Check this out:
// cpu_backend.h
#define CPU_BACKEND
class UseCPU;
#ifndef GPU_BACKEND
template<class Method = UseCPU>
struct Backend;
#endif
template<>
struct Backend<UseCPU>
{
char* Info() { return "CPU"; }
};
// gpu_backend.h
#define GPU_BACKEND
class UseGPU;
#ifndef CPU_BACKEND
template<class Method = UseGPU>
struct Backend;
#endif
template<>
struct Backend<UseGPU>
{
char* Info() { return "GPU"; }
};
// main.cpp
// Try to swap comments on headers
// and see how output changes
#include "cpu_backend.h"
//#include "gpu_backend.h"
#include <iostream>
template<class ... Method>
struct Work
{
Work()
{
std::cout << "I use " << backend.Info() << std::endl;
}
private:
Backend<Method ...> backend;
};
int main()
{
Work<> work;
// Uncomment these two while including both headers
//Work<UseCPU> cpuWork;
//Work<UseGPU> gpuWork;
return 0;
}
If you use MSVC you can simplify example above eliminating #define and #ifndef.
Trick: MSVC (2017 and maybe earlier versions) allow to omit that macros thresh, just ignoring the second declaration if they meet in
the same compilation unit, like this:
template<class Method = UseCPU>
struct Backend;
template<class Method = UseGPU>
struct Backend;
BUT this will be not standard. Standard does not allow specifying default template args twice.
Meanwhile, this solution has few drawback:
When you include both headers, someone still can say Work<> which will
use the backend specified by the first header you included.
However, it would be better if compiler forced a person to specify a
backend type explicitly in this circumstances, because otherwise it
relies on the header inclusion order which is bad (say hello to
macros).
Also, it assumes that both backends have the same API (like Info()
in my case)
Possible Fixes for those:
I am sure it is possible to make compiler give an error when both
headers are included and no explicit backend was specified, but it
probably involves more preprocessor things or some SFINAE...
If your backends do have different APIs, then you can insert a few
#ifdef where needed or (preferably) use C++17
if constexpr(std::is_same<Method, UseCPU>()::value) if you have access
to such cool features:)
Following my previous question. I've settled on using using directives to alias types inside my classes to avoid importing other stuff and polluting other headers that use these offending headers.
namespace MyLibrary {
namespace MyModule1 {
class MyClass1 {
public:
float X;
float Y;
MyClass1(float x, float y): X(x), Y(y) {}
};
} // namespace MyModule1
namespace MyModule2 {
class MyClass2 {
private:
// as suggested in linked question
using MyCustomType1 = MyLibrary::MyModule1::MyClass1;
public:
void DoSomething(MyCustomType1 parameter) {
std::cout << parameter.X << std::endl;
std::cout << parameter.Y << std::endl;
}
};
} // namespace MyModule2
} // namespace MyLibrary
int main(int argc, char* argv[])
{
MyLibrary::MyModule1::MyClass1 some_parameter(1.0f, 2.0f);
MyLibrary::MyModule2::MyClass2 some_var;
// Can't do this
// MyLibrary::MyModule2::MyClass2::MyCustomType1 some_other_var;
// But I can do this
some_var.DoSomething(some_parameter);
return 0;
}
How will the users outside of the MyLibrary namespace know what is MyCustomType1 if it is aliased inside a class (privately)?
Is my usage here of using legal, or is this a dirty hack I'm accidentally doing?
They will know for the simple reason you have to #include the declarations of both classes.
Having read this, and the previous question, I think the missing concept here is the concept of forward declarations.
Consider the following header file, let's called this file mymodule1_fwd.H:
namespace MyLibrary {
namespace MyModule1 {
class MyClass1;
} // namespace MyModule1
}
That's it. This is sufficient for you to declare MyClass2:
#include "mymodule1_fwd.H"
namespace MyModule2 {
class MyClass2 {
private:
// as suggested in linked question
using MyCustomType1 = MyLibrary::MyModule1::MyClass1;
public:
void DoSomething(MyCustomType1 parameter);
};
} // namespace MyModule2
Note that including this header file only will not really automatically get the entire MyModule class declaration. Also note the following:
You can't define the contents of the inline DoSomething() class method, because it actually uses the aliased type. This has the following consequences:
You have to define the DoSomething() method somewhere, in some way, probably inside the .C implementation translation module.
Similarly, you have to have declare the actual MyClass1 class from the mymodule1_fwd.H header file. I am using my own personal naming convention here, "filename_fwd.H" for forward declarations, the forward declaration header file; and "filename.H" for the actual class implementation, the implementation header file.
Callers of the DoSomething() method will have to explicitly #include the actual class declaration header file for MyClass, since they have to pass it as a parameter.
You can't really avoid the fact that the callers have to know the class that they're actually using to pass parameters. But only the callers of the DoSomething() method will need that. Something that uses other parts of the MyClass2, and don't invoke DoSomething(), don't need to know anything about MyClass1, and the actual class declaration won't be visible to them unless they explicitly #include the class implementation header file.
Now, if you still need DoSomething() to be inlined, for performance reasons, there are a couple of tricks that can be used, with preprocessor directives, that if someone #includes all the necessary header files, they'll get the inlined declaration of the DoSomething() method.
But that'll have to be another question.
How can I create bunch of methods that doesn't depend on any object ( in my file there is no classes , no objects , no main , nothing but the methods) all in one cpp/hpp file and how to declare them ?
Create a namespace. Something like this:
Utils.h
namespace Utils
{
void myMethod();
}
Utils.cpp
namespace Utils
{
void myMethod()
{
//Implementation
}
}
If you want them to be public, i.e. available in multiple translation units, the best way is to include them in a namespace, declare them in the header and implement them in a single implementation file:
//functions.h
namespace MyFunctions
{
void foo();
void goo();
}
//functions.cpp
namespace MyFunctions
{
void foo() {}
void goo() {}
}
IMPORTANT
If you provide the definition in the header, you should mark them inline, otherwise including that header in multiple translation units might result in a linker error:
//functions.h
inline void foo() {
//..
}
inline void goo() {
//..
}
If you only want them available in a translation unit, define them in that implementation file in an anonymous namespace (or declare them static):
//fileThatUsesFunctions.cpp
namespace
{
void foo() {}
void goo() {}
}
You declare them the same way you would in C. It can be within a namespace or outside of a namespace. There is no difference other than the fact that they are not in a class.
If you want to use the functions in C later you should prepend them with extern "C".
extern "C" void foo();
Nothing stops you from writing free functions. If you think that a function should be global then free functions are quite appropriate.
You should place them in a namespace. Naveen's example is spot on.
As an additional note, if you wish to hide certain functions or data units within the namespace (thereby mimicking 'private' access), place those functions and data units in an anonymous namespace, nested within the parent namespace. For example:
namespace Foo
{
publicFunction1();
publicFunction2();
namespace
{
privateFunction1();
std::vector<Bar> privateData;
}
}
Items within a nested, anonymous namespace are only accessible to the items within the parent namespace. I've found this to be singularly useful.
To define a function that doesn't depend on an object simply declare them directly.
// MyFile.h
int some_function();
// MyFile.cpp
int some_function() {
return 42;
}
Using C++ though it would be a good idea to declare them in a namespace though. This doesn't give them a dependcy on an object but does reduce global namespace pollution
// MyFile.h
namespace MyNamespace {
int some_function();
}
// MyFile.cpp
using MyNamespace;
int some_function() {
return 42;
}
I have some inline functions contained within a namespace in a header file and am not currently in a position to move them into a cpp file. Some of these inline functions use magic constants, for example:
// Foo.h
namespace Foo
{
const int BAR = 1234;
inline void someFunc()
{
// Do something with BAR
}
}
However, I want to make these magic constants private - any ideas how? My first thought was to use an anonymous namespace thus:
// Foo.h
namespace Foo
{
namespace
{
// 'private' constants here
const int BAR = 1234;
}
inline void someFunc()
{
// Do something with BAR
}
}
However, this doesn't work and Foo::BAR is available to any cpp file that includes Foo.h? Is there a way to do this without creating an implementation cpp file?
You can't, anonymous namespaces work for the translation unit they are defined in (or included into in your case).
You could consider moving them into a detail namespace to signal to the user that they are internal details:
namespace foo {
namespace detail {
int magic = 42;
}
// ... use detail::magic
}
How about:
namespace Foo {
class foo_detail {
private:
enum {
BAR = 1234,
};
friend void someFunc();
};
inline
void someFunc() {
// something with foo_detail::BAR
}
}
This makes the constant nonaccessible for anyone else than the functions you mark as friends. You can make the class nonconstructable by making the constructor private to make sure that noone does try to instanciate the class.
Put them in a special namespace or name them specially, combined with a project convention that such things are non-public:
namespace foo {
namespace detail { // as in "implementation details"
inline int answer() { return 42; }
const int perfect = 28;
}
std::string _question(); // not part of foo's "public interface" by convention
int this_is_public() {
using namespace detail; // now don't have to prefix detail::
return answer() + perfect + _question().length();
}
}
Anyone using names documented as non-public will circumvent any "protection" you try; which highlights the real concern: documenting what's part of the public interface and may be relied upon.
Unnamed namespaces solve a different problem: getting names unique to a particular TU. They won't help here.