How to make private functions in an API? - c++

I currently have the following header file in my API:
// my_library.h
namespace MyLibrary
{
// Private functions
long bar(long id);
unsigned long foo(long id);
// Public functions
void do_public_thing(long id);
}
This header file has implementations for each function in a my_library.cpp file. My issue is that I want to make bar and foo private functions, but still have their implementation in a separate .cpp file, so I can't use a blank namespace (at least I don't think so). What should I do?

I don't see any reason why you should expose your namespace API private functions in the header that does the public part of your API.
What you probably want is
// my_library.h
namespace MyLibrary {
// Public functions
void do_public_thing(long id);
}
// my_library.cpp
#include library.h
namespace {
// Private functions
long bar(long id) {
// Implementation
}
unsigned long foo(long id) {
// Implementation
}
}
void MyLibrary::do_public_thing(long id) {
// Implementation
long bar_result = bar(id);
unsingned long foo_result = foo(id);
}
The anonymous namespace would protect you from linker ambiguities in case that bar() or foo() are implemented in any other translation units.

Related

Where to put helper functions pertaining to class method in C++

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.

File scope data with C++ namespaces

I've got some embedded C++ code that's currently written in a very C-like way, and I'd like to convert it to use namespaces for better code organization. Currently I hide my private file scope functions and variables in anonymous namespaces, but I'm not sure where to hide it using this new pattern. Should I still use an anonymous namespace, or is adding it to the namespace in the .cpp file, but not the header file sufficient enough to prevent external access?
More specifically, I've got code that looks like this:
UI.h
#ifndef UI_H
#define UI_H
//Public data declarations
extern int g_UiPublicVar;
//Public function declarations
void UI_PublicFunc();
#endif
UI.cpp
#include "UI.h"
//Private data and functions
namespace
{
int m_PrivateVar = 10;
void privateFunc()
{
//Do stuff!
}
}
//Public data definitions
int g_UiPublicVar = 10;
//Public function definitions
void UI_PublicFunc()
{
m_PrivateVar++;
privateFunc();
}
...and I'd like to restructure it to look like this:
New UI.h
#ifndef UI_H
#define UI_H
namespace UI
{
//Public data declarations
extern int publicVar;
//Public function declarations
void publicFunc();
}
#endif
New UI.cpp
#include "UI.h"
namespace UI
{
//Public data definitions
int publicVar = 10;
//Public function definitions
void publicFunc()
{
m_PrivateVar++;
privateFunc();
}
}
...where should I put m_PrivateVar and privateFunc()?
The solution is to put it in an anonymous nested namespace for the private elements:
File UI.cpp:
namespace UI
{
namespace // nested private namespace
{
int m_PrivateVar = 10;
void privateFunc()
{
//Do stuff!
}
}
//Public definitions
...
}
The other compilation units then can't see it, as the anonymous namespace is unique for each compilation unit.
You can test this setting using a third compilation unit, including UI.h and trying to create access to the private function:
File main.cpp:
#include "UI.h"
namespace UI {
extern void privateFunc(); // Hijack temptative
}
int main(int ac, char**av)
{
UI::publicFunc(); // yes !!
UI::privateFunc(); // compiles, but generates a linking error
// private remains private :-) !!!
}
Even if the hijack temptative would also use an anonymous namespace, it wouldn't work and still result in linking errors, because, as already said, the anonymous namespace is unique for each compilation unit.

creating methods that doesn't depend on a object

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;
}

Is pimpl compatible with anonymous namespaces?

I am trying to use the pimpl pattern and define the implementation class in an anonymous namespace. Is this possible in C++? My failed attempt is described below.
Is it possible to fix this without moving the implementation into a namespace with a name (or the global one)?
class MyCalculatorImplementation;
class MyCalculator
{
public:
MyCalculator();
int CalculateStuff(int);
private:
MyCalculatorImplementation* pimpl;
};
namespace // If i omit the namespace, everything is OK
{
class MyCalculatorImplementation
{
public:
int Calculate(int input)
{
// Insert some complicated calculation here
}
private:
int state[100];
};
}
// error C2872: 'MyCalculatorImplementation' : ambiguous symbol
MyCalculator::MyCalculator(): pimpl(new MyCalculatorImplementation)
{
}
int MyCalculator::CalculateStuff(int x)
{
return pimpl->Calculate(x);
}
No, the type must be at least declared before the pointer type can be used, and putting anonymous namespace in the header won't really work. But why would you want to do that, anyway? If you really really want to hide the implementation class, make it a private inner class, i.e.
// .hpp
struct Foo {
Foo();
// ...
private:
struct FooImpl;
boost::scoped_ptr<FooImpl> pimpl;
};
// .cpp
struct Foo::FooImpl {
FooImpl();
// ...
};
Foo::Foo() : pimpl(new FooImpl) { }
Yes. There is a work around for this. Declare the pointer in the header file as void*, then use a reinterpret cast inside your implementation file.
Note: Whether this is a desirable work-around is another question altogether. As is often said, I will leave that as an exercise for the reader.
See a sample implementation below:
class MyCalculator
{
public:
MyCalculator();
int CalculateStuff(int);
private:
void* pimpl;
};
namespace // If i omit the namespace, everything is OK
{
class MyCalculatorImplementation
{
public:
int Calculate(int input)
{
// Insert some complicated calculation here
}
private:
int state[100];
};
}
MyCalculator::MyCalculator(): pimpl(new MyCalculatorImplementation)
{
}
MyCalaculator::~MyCalaculator()
{
// don't forget to cast back for destruction!
delete reinterpret_cast<MyCalculatorImplementation*>(pimpl);
}
int MyCalculator::CalculateStuff(int x)
{
return reinterpret_cast<MyCalculatorImplementation*>(pimpl)->Calculate(x);
}
No, you can't do that. You have to forward-declare the Pimpl class:
class MyCalculatorImplementation;
and that declares the class. If you then put the definition into the unnamed namespace, you are creating another class (anonymous namespace)::MyCalculatorImplementation, which has nothing to do with ::MyCalculatorImplementation.
If this was any other namespace NS, you could amend the forward-declaration to include the namespace:
namespace NS {
class MyCalculatorImplementation;
}
but the unnamed namespace, being as magic as it is, will resolve to something else when that header is included into other translation units (you'd be declaring a new class whenever you include that header into another translation unit).
But use of the anonymous namespace is not needed here: the class declaration may be public, but the definition, being in the implementation file, is only visible to code in the implementation file.
If you actually want a forward declared class name in your header file and the implementation in an anonymous namespace in the module file, then make the declared class an interface:
// header
class MyCalculatorInterface;
class MyCalculator{
...
MyCalculatorInterface* pimpl;
};
//module
class MyCalculatorInterface{
public:
virtual int Calculate(int) = 0;
};
int MyCalculator::CalculateStuff(int x)
{
return pimpl->Calculate(x);
}
namespace {
class MyCalculatorImplementation: public MyCalculatorInterface {
...
};
}
// Only the ctor needs to know about MyCalculatorImplementation
// in order to make a new one.
MyCalculator::MyCalculator(): pimpl(new MyCalculatorImplementation)
{
}
markshiz and quamrana provided the inspiration for the solution below.
class Implementation, is intended to be declared in a global header file and serves as a void* for any pimpl application in your code base. It is not in an anonymous/unnamed namespace, but since it only has a destructor the namespace pollution remains acceptably limited.
class MyCalculatorImplementation derives from class Implementation. Because pimpl is declared as std::unique_ptr<Implementation> there is no need to mention MyCalculatorImplementation in any header file. So now MyCalculatorImplementation can be implemented in an anonymous/unnamed namespace.
The gain is that all member definitions in MyCalculatorImplementation are in the anonymous/unnamed namespace. The price you have to pay, is that you must convert Implementation to MyCalculatorImplementation. For that purpose a conversion function toImpl() is provided.
I was doubting whether to use a dynamic_cast or a static_cast for the conversion. I guess the dynamic_cast is the typical prescribed solution; but static_cast will work here as well and is possibly a little more performant.
#include <memory>
class Implementation
{
public:
virtual ~Implementation() = 0;
};
inline Implementation::~Implementation() = default;
class MyCalculator
{
public:
MyCalculator();
int CalculateStuff(int);
private:
std::unique_ptr<Implementation> pimpl;
};
namespace // Anonymous
{
class MyCalculatorImplementation
: public Implementation
{
public:
int Calculate(int input)
{
// Insert some complicated calculation here
}
private:
int state[100];
};
MyCalculatorImplementation& toImpl(Implementation& impl)
{
return dynamic_cast<MyCalculatorImplementation&>(impl);
}
}
// no error C2872 anymore
MyCalculator::MyCalculator() : pimpl(std::make_unique<MyCalculatorImplementation>() )
{
}
int MyCalculator::CalculateStuff(int x)
{
return toImpl(*pimpl).Calculate(x);
}

Hiding private constants in an inline namespace header

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.