Is it possible to use a class defined in an anonymous namespace as a parameter in a private member function? I haven’t found a way to forward declare AnonymousHelperClass in the header.
// C.h
class C
{
// ...
private:
void Boing(AnonymousHelperClass &helper);
};
.
// C.cpp
namespace
{
class AnonymousHelperClass
{
// . . .
};
}
C::Boing(AnonymousHelperClass &helper)
{
// ...
}
No, because there is no way to name the type in the header file.
However, you could turn the private member function into a template:
// C.h
class C
{
public:
void Foo();
private:
template <typename TAnonymousHelper>
void Boing(TAnonymousHelper&);
};
Then define it in the source file and use it with the AnonymousHelperClass:
// C.cpp
#include "C.h"
namespace
{
class AnonymousHelperClass { };
}
template <typename TAnonymousHelper>
void C::Boing(TAnonymousHelper& x) { }
void C::Foo()
{
AnonymousHelperClass x;
Boing(x);
}
Though really, it's probably easier just to rework your logic such that the private member function can be a namespace-scope function in the .cpp file.
No, because unnamed namespaces (that's what they're actually called) are defined like this in the C++ standard:
7.3.1.1 Unnamed namespaces [namespace.unnamed]
1. An unnamed-namespace-definition behaves as if it were replaced by
namespace unique { /* empty body */ }
using namespace unique;
namespace unique { namespace-body }
where all occurrences of unique in a translation unit are replaced by
the same identifier and this identifier differs from all other
identifiers in the entire program.
So with your class it's equivalent to:
namespace SomeUniqueNameGeneratedByTheCompiler {}
using namespace SomeUniqueNameGeneratedByTheCompiler;
namespace SomeUniqueNameGeneratedByTheCompiler
{
class AnonymousHelperClass
{
// . . .
};
}
So the full qualification of the AnonymousHelperClass class is ::SomeUniqueNameGeneratedByTheCompiler::AnonymousHelperClass, not ::AnonymousHelperClass. So even if you did this:
class AnonymousHelperClass; // Forward declaration
class C
{
// ...
private:
void Boing(AnonymousHelperClass &helper);
};
That forward declaration refers to a different AnonymousHelperClass. You could put the forward declaration in the SomeUniqueNameGeneratedByTheCompiler namespace, but since only the compiler knows this name, it can't be done.
Related
I've been using a dirty trick where I use unnamed namespaces to specify different behavior for each file (it is for unit-testing). It feels like it shouldn't be well-defined, but it works on every major compiler released in the past six years.
I first forward-declare a bunch of classes in an anonymouse namespace:
namespace {
class context_check;
class context_block;
class register_test;
} // namespace
Then I declare a class and make these classes friends:
struct test_case
{
// ...
};
class context {
// ...
private:
// TODO: this feels like ODR-violation...
friend class context_check;
friend class context_block;
friend class register_test;
private:
void add_test(test_case&& test)
{
// ...
}
// ...
};
And in each cpp file I have following declarations (for tha sake of simplicity I copy and pasted them here, but in reality I declare the content of unnamed namespace in a header):
// A.cpp
namespace {
extern context file_context;
class register_test {
public:
register_test(const char* test_name, test_case&& test)
{
file_context.add_test(std::move(test));
}
};
} // namespace
register_test register_test_1( test_case{"test1"} );
// B.cpp
namespace {
extern context file_context;
class register_test {
public:
register_test(const char* test_name, test_case&& test)
{
file_context.add_test(std::move(test));
}
};
} // namespace
register_test register_test_2( test_case{"test2"} );
So each TU has its own definitions of register_test, context_check etc.
Is this well-defined? Feels like it should be an UB...
Seems to violate the following condition required by ODR, as stated on https://en.cppreference.com/w/cpp/language/definition:
There can be more than one definition in a program of each of the following: class type, [...], as long as all of the following is true:
[...]
name lookup from within each definition finds the same entities (after overload-resolution), except that [...]
None of the exceptions are relevant and lookup for e.g. context_check in friend class context_check;, which is part of the definition of context, finds an internal linkage entity, which cannot be the same if the definition is included in multiple translation units.
The actual corresponding rule of the standard can be found e.g. in [basic.def.odr]/13.9 of the post-C++20 draft.
I have a class which I want to be in a namespace. I have been doing it like
namespace ns {
class A;
}
class ns::A {
...
public:
A();
};
and I define the constructor in a separate file like
ns::A::A() {
...
}
My question is about the correct way of defining the constructor. Is that the correct way, or should I add the namespace to the declaration?
namespace ns {
class A;
}
class ns::A {
...
public:
ns::A();
};
And if that's the case, how is the constructor defined in a separate file?
how is the constructor defined in a separate file?
You can do it as shown below:
header.h
#ifndef HEADER_H
#define HEADER_H
namespace NS
{
//class definition
class A
{
public:
//declaration for default constructor
A();
//declaration for member function
void printAge();
private:
int age;
};
}
#endif
source.cpp
#include"header.h"
#include <iostream>
namespace NS
{
//define default constructor
A::A(): age(0)
{
std::cout<<"default consttuctor used"<<std::endl;
}
//define member function printAge
void A::printAge()
{
std::cout<<age<<std::endl;
}
}
main.cpp
#include <iostream>
#include"header.h"
int main()
{
NS::A obj; //this uses default constructor of class A inside namespace NS
obj.printAge();
return 0;
}
Also don't forget to use header guards inside the header file to avoid cyclic dependency(if any).
The output of the program can be seen here
Some of the changes that i made include:
Added include guard in header file header.h.
Added declarations for the default constructor and a member function called printAge inside class A inside the header file.
Defined the default constructor and the member function printAge inside source.cpp.
Used constructor initializer list in the default constructor of class A inside source.cpp.
Method 2
Here we use the scope resolution operator :: to be in the scope of the namespace NS and then define the member functions as shown below:
source.cpp
#include"header.h"
#include <iostream>
//define default constructor
NS::A::A(): age(0)
{
std::cout<<"default consttuctor used"<<std::endl;
}
//define member function printAge
void NS::A::printAge()
{
std::cout<<age<<std::endl;
}
The output of method 2 can be seen here
There are a few different ways to define a constructor (or a method) for a class which is inside a namespace.
Put the definition inside a namespace
namespace ns
{
A::A()
{
...
}
...
}
Use a qualified name for the class
ns::A::A()
{
...
}
My favorite one - "import" the namespace, then forget about its existence in current source file.
using namespace ns;
...
A::A()
{
...
}
Different style may be appropriate in different situations. If your class is big, 1 or 3 may be best. If you have many small classes, 2 may be best.
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);
}
I want to use an 3rd party library without using its header file. My code resides in its own namespace, therefore I can't use conventional forward declaration as I don't want to pollute the global namespace. Currently I have something like that:
3rd-party-library.h----
typedef struct {...} LibData;
void lib_func (LibData *);
my-source.h-----
namespace foo {
/*forward declaration of LibData*/
class Abcd {
public:
void ghj();
private:
Libdata *data_;
};
}//namespace foo
my-source.cpp-----
#include "my-source.h"
#include <3rd-party-library.h>
namespace foo {
typedef ::LibData LibData;
void Abcd::ghj() {
//do smth with data_
}
}//namespace foo
Is it possible to forward declare a global type in a way that it would reside in an namespace? Plain simple typedef does not work.
For a forward declaration to work, you need to forward declare an object in the proper namespace. Since the original object resides in the global namespace, you need to forward declare it in the global namespace.
If you don't like that, you can always wrap the thing in your own structure:
namespace foo {
struct libDataWrapper; }
and in your own cpp define this structure. Or you can always resort to void* and the like, if you're up to that sort of thing.
since you are using pointer, i''' just forward declare a dummy object inside your own namespace, then use reinterpret_cast to bind the actual object to existing pointer.
your-source.h
namespace foo {
//forward declare
class externalObj;
class yourObj
{
public:
yourObj();
~yourObj();
void yourFunction();
private:
externalObj* pExt;
};
}
your-implementation.cpp
#include "your-source.h"
#include "externalObj-header.h"
namespace foo {
yourObj::yourObj() :
pExt ( reinterpret_cast<externalObj*>(new ::externalObj()) )
{
}
yourObj::~yourObj()
{
}
void yourObj::yourFunction()
{
reinterpret_cast<::externalObj*>(pExt)->externalFunction();
}
}
Can't you just simply wrap the include for the third-party library in its own namespace?
namespace ThirdParty {
#include "thirdparty.h"
}
namespace foo {
... your code
ThirdParty::LibData *d;
}
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.