There is no feature that control visibility/accessibility of class in C++.
Is there any way to fake it?
Are there any macro/template/magic of C++ that can simulate the closest behavior?
Here is the situation
Util.h (library)
class Util{
//note: by design, this Util is useful only for B and C
//Other classes should not even see "Util"
public: static void calculate(); //implementation in Util.cpp
};
B.h (library)
#include "Util.h"
class B{ /* ... complex thing */ };
C.h (library)
#include "Util.h"
class C{ /* ... complex thing */ };
D.h (user)
#include "B.h" //<--- Purpose of #include is to access "B", but not "Util"
class D{
public: static void a(){
Util::calculate(); //<--- should compile error
//When ctrl+space, I should not see "Util" as a choice.
}
};
My poor solution
Make all member of Util to be private, then declare :-
friend class B;
friend class C;
(Edit: Thank A.S.H for "no forward declaration needed here".)
Disadvantage :-
It is a modifying Util to somehow recognize B and C.
It doesn't make sense in my opinion.
Now B and C can access every member of Util, break any private access guard.
There is a way to enable friend for only some members but it is not so cute, and unusable for this case.
D just can't use Util, but can still see it.
Util is still a choice when use auto-complete (e.g. ctrl+space) in D.h.
(Edit) Note: It is all about convenience for coding; to prevent some bug or bad usage / better auto-completion / better encapsulation. This is not about anti-hacking, or prevent unauthorized access to the function.
(Edit, accepted):
Sadly, I can accept only one solution, so I subjectively picked the one that requires less work and provide much flexibility.
To future readers, Preet Kukreti (& texasbruce in comment) and Shmuel H. (& A.S.H is comment) has also provided good solutions that worth reading.
I think that the best way is not to include Util.h in a public header at all.
To do that, #include "Util.h" only in the implementation cpp file:
Lib.cpp:
#include "Util.h"
void A::publicFunction()
{
Util::calculate();
}
By doing that, you make sure that changing Util.h would make a difference only in your library files and not in the library's users.
The problem with this approach is that would not be able to use Util in your public headers (A.h, B.h). forward-declaration might be a partial solution for this problem:
// Forward declare Util:
class Util;
class A {
private:
// OK;
Util *mUtil;
// ill-formed: Util is an incomplete type
Util mUtil;
}
One possible solution would be to shove Util into a namespace, and typedef it inside the B and C classes:
namespace util_namespace {
class Util{
public:
static void calculate(); //implementation in Util.cpp
};
};
class B {
typedef util_namespace::Util Util;
public:
void foo()
{
Util::calculate(); // Works
}
};
class C {
typedef util_namespace::Util Util;
public:
void foo()
{
Util::calculate(); // Works
}
};
class D {
public:
void foo()
{
Util::calculate(); // This will fail.
}
};
If the Util class is implemented in util.cpp, this would require wrapping it inside a namespace util_namespace { ... }. As far as B and C are concerned, their implementation can refer to a class named Util, and nobody would be the wiser. Without the enabling typedef, D will not find a class by that name.
One way to do this is by friending a single intermediary class whose sole purpose is to provide an access interface to the underlying functionality. This requires a bit of boilerplate. Then A and B are subclasses and hence are able to use the access interface, but not anything directly in Utils:
class Util
{
private:
// private everything.
static int utilFunc1(int arg) { return arg + 1; }
static int utilFunc2(int arg) { return arg + 2; }
friend class UtilAccess;
};
class UtilAccess
{
protected:
int doUtilFunc1(int arg) { return Util::utilFunc1(arg); }
int doUtilFunc2(int arg) { return Util::utilFunc2(arg); }
};
class A : private UtilAccess
{
public:
int doA(int arg) { return doUtilFunc1(arg); }
};
class B : private UtilAccess
{
public:
int doB(int arg) { return doUtilFunc2(arg); }
};
int main()
{
A a;
const int x = a.doA(0); // 1
B b;
const int y = b.doB(0); // 2
return 0;
}
Neither A or B have access to Util directly. Client code cannot call UtilAccess members via A or B instances either. Adding an extra class C that uses the current Util functionality will not require modification to the Util or UtilAccess code.
It means that you have tighter control of Util (especially if it is stateful), keeping the code easier to reason about since all access is via a prescribed interface, instead of giving direct/accidental access to anonymous code (e.g. A and B).
This requires boilerplate and doesn't automatically propagate changes from Util, however it is a safer pattern than direct friendship.
If you do not want to have to subclass, and you are happy to have UtilAccess change for every using class, you could make the following modifications:
class UtilAccess
{
protected:
static int doUtilFunc1(int arg) { return Util::utilFunc1(arg); }
static int doUtilFunc2(int arg) { return Util::utilFunc2(arg); }
friend class A;
friend class B;
};
class A
{
public:
int doA(int arg) { return UtilAccess::doUtilFunc1(arg); }
};
class B
{
public:
int doB(int arg) { return UtilAccess::doUtilFunc2(arg); }
};
There are also some related solutions (for tighter access control to parts of a class), one called Attorney-Client and the other called PassKey, both are discussed in this answer: clean C++ granular friend equivalent? (Answer: Attorney-Client Idiom) . In retrospect, I think the solution I have presented is a variation of the Attorney-Client idiom.
Related
I'm writing a C++ wrapper library around a number of different hardware libraries for embedded systems (firmware level), using various libraries from different vendors (C or C++). The API exposed by the header files should be vendor agnostic... all Vendor header libraries are not included in any of my header files.
A common pattern I have is making the vendor member data opaque, by only using a pointer to some "unknown" vendor struct/class/typedef/pod type.
// myclass.h
class MyClass
{
...
private:
VendorThing* vendorData;
};
and implementation (note: each implementation is vendor specific; all have the same *.h file)
// myclass_for_vendor_X.cpp
#include "vendor.h"
... {
vendorData->doSomething();
or
VendorAPICall(vendorData,...);
or whatever
The problem I have is that VendorThing can be lots of different things. It could be a class, struct, type or pod. I don't know, and I don't want to care in the header file. But if you pick the wrong one, then it doesn't compile if the vendor header file is included as well as my header file. For example, if this the actual declaration of VendorThing in "vendor.h":
typedef struct { int a; int b; } VendorThing;
Then you can't just forward-declare VendorThing as class VendorThing;. I don't care about what the type of VendorThing is at all, all I want is the public interface to think of it as void * (i.e allocate space for a pointer and that is it), and the implementation think of it using the correct pointer type.
Two solutions I have come across are the "d-pointer" method found in Qt, where you add a level of indirection by replacing VendorThing a new struct VendorThingWrapper
// myclass.h
struct VendorThingWrapper;
class MyClass
{
...
private:
VendorThingWrapper* vendorDataWrapper;
};
and in your cpp file
// myclass.cpp
#include "vendor.h"
struct VendorThingWrapper {
VendorThing* vendorData;
};
... {
vendorDataWrapper->vendorData->doSomething();
}
but this adds a second pointer dereference, which is not a huge deal, but as this is targeting embedded systems, I don't want to add that overhead just because the language can't do what I want.
The other thing is just declare it void
// myclass.h
class MyClass
{
...
private:
void* vendorDataUntyped;
};
and in the implememtation
//myclass.cpp
#include "vendor.h"
#define vendorData ((VendorThing*)vendorDataUntyped)
... {
vendorData->doSomething();
}
but #define's always leave a bad taste in my mouth. There must be something better.
You can avoid the additional pointer dereference by using:
#include "vendor.h"
struct VendorThingWrapper : public VendorThing {};
Of course, at that point, it makes more sense to use the name MyClassData instead of VendorThingWrapper.
MyClass.h:
struct MyClassData;
class MyClass
{
public:
MyClass();
~MyClass();
private:
MyClassData* myClassData;
};
MyClass.cpp:
struct MyClassData : public VendorThing {};
MyClass::MyClass() : myClassData(new MyClassData())
{
}
MyClass::~MyClass()
{
delete myClassData;
}
Update
I was able to compile and build the following program. The unnamed struct is not a problem.
struct MyClassData;
class MyClass
{
public:
MyClass();
~MyClass();
private:
MyClassData* myClassData;
};
typedef struct { int a; int b; } VendorThing;
struct MyClassData : public VendorThing
{
};
MyClass::MyClass() : myClassData(new MyClassData())
{
myClassData->a = 10;
myClassData->b = 20;
}
MyClass::~MyClass()
{
delete myClassData;
}
int main() {}
If you are willing to go the route of the VendorThingWrapper, then you simply allow the wrapper to contain the data itself, rather than a pointer to it. This gives you the abstraction layer and avoids the extra dereference.
// myclass.cpp
#include "vendor.h"
struct VendorThingWrapper {
VendorThing vendorData;
};
... {
vendorDataWrapper->vendorData.doSomething();
}
I have the following situation:
namespace MyFramework {
class A {
void some_function_I_want_B_to_use() {}
};
class B {
B() {
some_function_I_want_B_to_use() {}
}
};
}
where I want the some_function_I_want_B_to_use to not be visible outside of the MyFramework namespace, but I do want it to be visible to anyone inside of MyFramework (alternatively, visible to just class B is also ok). I've got a number of methods like this, is the only way to hide them from the public API of MyFramework to make all classes within MyFramework friends? I was also considering placing all "lower-level" classes inside of B, but I don't want to go down that route until I'm sure it would accomplish the ability to access all of A's methods from inside of B but not from outside of MyFramework.
To restate, I've got a framework that's all created within one namespace, and each class has methods that are useful to the general public using the framework. However, each class also has a few methods that complicate the public API but are needed for the framework to function properly.
I want the some_function_I_want_B_to_use to not be visible outside of the MyFramework namespace, but I do want it to be visible to anyone inside of MyFramework.
In summary, you want something similar to packages in Java.
Unfornately for you, that is not possible with namespaces. Every class included in a namespace is accessible from the outer of the namespace: namespaces are open.
The solution is usually to add another namespace for implementation details:
namespace MyFramework
{
// Implementation details
// Should not be used by the user
namespace detail
{
class A
{
public:
void func();
};
}
class B
{
public:
B()
{
A a;
a.func();
}
};
}
Don't forget to add a comment stating the detail namespace is not to be used by user.
Pimpl idiom, frequently called Compilation Firewall, is what you are looking for. The whole Qt is implemented using this idiom.
// A.hpp
namespace MyFramework {
class A {
private:
class Private;
Private* implementation;
};
}
// A_Private.hpp
#include "A.hpp"
namespace MyFramework {
class A::Private {
public:
void some_function_I_want_B_to_use() {}
};
}
// A.cpp
#include "A_Private.hpp"
namespace MyFramework {
A::A() {
implementation->some_function_I_want_B_to_use();
}
}
// B.hpp
#include "A.hpp"
namespace MyFramework {
class B {
B();
A a;
};
}
// B.cpp
#include "A_Private.hpp"
namespace MyFramework {
B::B() {
a.implementation->some_function_I_want_B_to_use();
}
}
NOTE: Of course A_Private.hpp does not go into the include directory of you framework final distribution, i.e. it remains package private as you require.
The example is very basic. Of course it can be made more advanced and robust. Additionally, Pimpl has lots of other advantages. For all this information refer to:
GotW #100: Compilation Firewalls (Difficulty: 6/10)
GotW #101: Compilation Firewalls, Part 2 (Difficulty: 8/10)
Pimp My Pimpl — Reloaded
Pimp My Pimpl
Dpointer
The common convention, e.g. in Boost, is a nested namespace called detail.
If you want to enforce the accessibility you can always instead use a nested class called detail. The class provides accessibility checking, but lacks extensibility like a namespace. However, a detail scope will rarely if ever need extension.
So, in all its ugliness,
namespace my_framework {
class detail
{
private:
static void some_function_I_want_B_to_use() {}
public:
class A
{};
class B
{
B() { some_function_I_want_B_to_use(); }
};
};
typedef detail::A A; // "using detail::A"
typedef detail::B B; // "using detail::B"
} // namespace my_framework
In passing, note that class B (straight from the question) has a private default constructor so no instances of it can be created.
Very new to c++ having trouble calling a function from another class.
Class B inherits from Class A, and I want class A to be able to call a function created in class B.
using namespace std;
class B;
class A
{
public:
void CallFunction ()
{
B b;
b.bFunction();
}
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
It all looks fine on screen (no obvious errors) but when I try to compile it i get an error C2079 'b' uses undefined class B.
I've tried making them pointers/ friends but I'm getting the same error.
void CallFunction ()
{ // <----- At this point the compiler knows
// nothing about the members of B.
B b;
b.bFunction();
}
This happens for the same reason that functions in C cannot call each other without at least one of them being declared as a function prototype.
To fix this issue we need to make sure both classes are declared before they are used. We separate the declaration from the definition. This MSDN article explains in more detail about the declarations and definitions.
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{ ... }
};
void A::CallFunction ()
{
B b;
b.bFunction();
}
What you should do, is put CallFunction into *.cpp file, where you include B.h.
After edit, files will look like:
B.h:
#pragma once //or other specific to compiler...
using namespace std;
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
B.cpp
#include "B.h"
void A::CallFunction(){
//use B object here...
}
Referencing to your explanation, that you have tried to change B b; into pointer- it would be okay, if you wouldn't use it in that same place. You can use pointer of undefined class(but declared), because ALL pointers have fixed byte size(4), so compiler doesn't have problems with that. But it knows nothing about the object they are pointing to(simply: knows the size/boundary, not the content).
So as long as you are using the knowledge, that all pointers are same size, you can use them anywhere. But if you want to use the object, they are pointing to, the class of this object must be already defined and known by compiler.
And last clarification: objects may differ in size, unlike pointers. Pointer is a number/index, which indicates the place in RAM, where something is stored(for example index: 0xf6a7b1).
class B is only declared but not defined at the beginning, which is what the compiler complains about. The root cause is that in class A's Call Function, you are referencing instance b of type B, which is incomplete and undefined. You can modify source like this without introducing new file(just for sake of simplicity, not recommended in practice):
using namespace std;
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
// postpone definition of CallFunction here
void A::CallFunction ()
{
B b;
b.bFunction();
}
in A you have used a definition of B which is not given until then , that's why the compiler is giving error .
Forward declare class B and swap order of A and B definitions: 1st B and 2nd A. You can not call methods of forward declared B class.
Here's my solution to the issue. Tried to keep it straight and simple.
#include <iostream>
using namespace std;
class Game{
public:
void init(){
cout << "Hi" << endl;
}
}g;
class b : Game{ //class b uses/imports class Game
public:
void h(){
init(); //Use function from class Game
}
}A;
int main()
{
A.h();
return 0;
}
You can also have a look at the curiously recurring template pattern and solve your problem similar to this:
template<typename B_TYPE>
struct A
{
int callFctn()
{
B_TYPE b;
return b.bFctn();
}
};
struct B : A<B>
{
int bFctn()
{
return 5;
}
};
int main()
{
A<B> a;
return a.callFctn();
}
I am trying to do unit testing (using the Boost unit testing framework) on a C++ class called VariableImpl. Here are the details.
class Variable
{
public:
void UpdateStatistics (void) {
// compute mean based on m_val and update m_mean;
OtherClass::SendData (m_mean);
m_val.clear ();
}
virtual void RecordData (double) = 0;
protected:
std::vector<double> m_val;
private:
double m_mean;
};
class VariableImpl : public Variable
{
public:
virtual void RecordData (double d) {
// Put data in m_val
}
};
How can I check that the mean is computed correctly? Note that 1) m_mean is protected and 2) UpdateStatistics calls a method of another class and then clears the vector.
The only way I can see would be to add a getter (for instance, GetMean), but I don't like this solution at all, nor I think it is the most elegant.
How should I do?
And what should I do if I were to test a private method instead of a private variable?
Well, unit testing should test units and ideally every class is a self-contained unit – this follows directly from the single responsibility principle.
So testing private members of a class shouldn’t be necessary – the class is a black box that can be covered in a unit test as-is.
On the other hand, this isn’t always true, and sometimes with good reasons (for instance, several methods of the class could rely on a private utility function that should be tested). One very simple, very crufty but ultimately successful solution is to put the following into your unit-test file, before including the header that defines your class:
#define private public
Of course, this destroys encapsulation and is evil. But for testing, it serves the purpose.
For a protected method/variable, inherit a Test class from the class and do your testing.
For a private, introduce a friend class. It isn't the best of solutions, but it can do the work for you.
Or this hack:
#define private public
In general, I agree with what others have said on here - only the public interface should be unit tested.
Nevertheless, I've just had a case where I had to call a protected method first, to prepare for a specific test case. I first tried the #define protected public approach mentioned above; this worked with Linux/GCC, but failed with Windows and Visual Studio.
The reason was that changing protected to public also changed the mangled symbol name and thus gave me linker errors: the library provided a protected __declspec(dllexport) void Foo::bar() method, but with the #define in place, my test program expected a public __declspec(dllimport) void Foo::bar() method which gave me an unresolved symbol error.
For this reason, I switched to a friend based solution, doing the following in my class header:
// This goes in Foo.h
namespace unit_test { // Name this anything you like
struct FooTester; // Forward declaration for befriending
}
// Class to be tested
class Foo
{
...
private:
bool somePrivateMethod(int bar);
// Unit test access
friend struct ::unit_test::FooTester;
};
And in my actual test case, I did this:
#include <Foo.h>
#include <boost/test/unit_test.hpp>
namespace unit_test {
// Static wrappers for private/protected methods
struct FooTester
{
static bool somePrivateMethod(Foo& foo, int bar)
{
return foo.somePrivateMethod(bar);
}
};
}
BOOST_AUTO_TEST_SUITE(FooTest);
BOOST_AUTO_TEST_CASE(TestSomePrivateMethod)
{
// Just a silly example
Foo foo;
BOOST_CHECK_EQUAL(unit_test::FooTester::somePrivateMethod(foo, 42), true);
}
BOOST_AUTO_TEST_SUITE_END();
This works with Linux/GCC as well as Windows and Visual Studio.
A good approach to test the protected data in C++ is the assignment of a friend proxy class:
#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test
class MyClass
{
private:
int MyMethod();
FRIEND_TEST(MyClassTest, MyMethod);
};
class MyClassTest : public testing::Test
{
public:
// ...
void Test1()
{
MyClass obj1;
ASSERT_TRUE(obj1.MyMethod() == 0);
}
void Test2()
{
ASSERT_TRUE(obj2.MyMethod() == 0);
}
MyClass obj2;
};
TEST_F(MyClassTest, PrivateTests)
{
Test1();
Test2();
}
See more Google Test (gtest).
Unit test VariableImpl such that if its behavior is ensured, so is Variable.
Testing internals isn't the worst thing in the world, but the goal is that they can be anything as long as the interfaces contracts are ensured. If that means creating a bunch of weird mock implementations to test Variable, then that is reasonable.
If that seems like a lot, consider that implementation inheritance doesn't create great separation of concerns. If it is hard to unit test, then that is a pretty obvious code smell for me.
While in my opinion the need of testing private members/methods of a class is a code smell, I think that is technically feasible in C++.
As an example, suppose you have a Dog class with private members/methods except for the public constructor:
#include <iostream>
#include <string>
using namespace std;
class Dog {
public:
Dog(string name) { this->name = name; };
private:
string name;
string bark() { return name + ": Woof!"; };
static string Species;
static int Legs() { return 4; };
};
string Dog::Species = "Canis familiaris";
Now for some reason you would like to test the private ones. You could use privablic to achieve that.
Include a header named privablic.h along with the desired implementation like that:
#include "privablic.h"
#include "dog.hpp"
then map some stubs according to types of any instance member
struct Dog_name { typedef string (Dog::*type); };
template class private_member<Dog_name, &Dog::name>;
...and instance method;
struct Dog_bark { typedef string (Dog::*type)(); };
template class private_method<Dog_bark, &Dog::bark>;
do the same with all static instance members
struct Dog_Species { typedef string *type; };
template class private_member<Dog_Species, &Dog::Species>;
...and static instance methods.
struct Dog_Legs { typedef int (*type)(); };
template class private_method<Dog_Legs, &Dog::Legs>;
Now you can test them all:
#include <assert.h>
int main()
{
string name = "Fido";
Dog fido = Dog(name);
string fido_name = fido.*member<Dog_name>::value;
assert (fido_name == name);
string fido_bark = (&fido->*func<Dog_bark>::ptr)();
string bark = "Fido: Woof!";
assert( fido_bark == bark);
string fido_species = *member<Dog_Species>::value;
string species = "Canis familiaris";
assert(fido_species == species);
int fido_legs = (*func<Dog_Legs>::ptr)();
int legs = 4;
assert(fido_legs == legs);
printf("all assertions passed\n");
};
Output:
$ ./main
all assertions passed
You can look at the sources of test_dog.cpp and dog.hpp.
DISCLAIMER: Thanks to insights of other clever people, I have assembled the aforementioned "library" able to access to private members and methods of a given C++ class without altering its definition or behaviour. In order to make it work it's (obviously) required to know and include the implementation of the class.
NOTE: I revised the content of this answer in order to follow directives suggested by reviewers.
I generally suggest testing the public interface of your classes, not the private/protected implementations. In this case, if it can't be observed from the outside world by a public method, then the unit test may not need to test it.
If the functionality requires a child class, either unit test the real derived class OR create your own test derived class that has an appropriate implementation.
Example from the Google testing framework:
// foo.h
#include "gtest/gtest_prod.h"
class Foo {
...
private:
FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
int Bar(void* x);
};
// foo_test.cc
...
TEST(FooTest, BarReturnsZeroOnNull) {
Foo foo;
EXPECT_EQ(0, foo.Bar(NULL));
// Uses Foo's private member Bar().
}
The main idea is the use of the friend C++ keyword.
You can extend this example as follows:
// foo.h
#ifdef TEST_FOO
#include "gtest/gtest_prod.h"
#endif
class Foo {
...
private:
#ifdef TEST_FOO
FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
#endif
int Bar(void* x);
};
You can define the TEST_FOO preprocessor symbol in two ways:
within the CMakeLists.txt file
option(TEST "Run test ?" ON)
if (TEST)
add_definitions(-DTEST_FOO)
endif()
as arguments to your compiler
g++ -D TEST $your_args
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);
}