I am writing a namespace that requires certain functions inside to have access to a particular variable (also declared within the namespace). Normally when I do this, I have the variable declared in the .cpp file to prevent outside access to it.
.h
namespace Example
{
int myFunc();
}
.cpp
namespace Example
{
int hiddenVar;
int myFunc()
{
.. do something with hiddenVar
return someValue;
}
}
My problem is that I need to define a template function that requires access to this hidden variable. Unfortunately since the body of the template function must be defined in the header file it wont have access to the variable hidden in the .cpp.
.h
namespace Example
{
template< typename T >
void myFunc( const T& myT )
{
.. do something with hiddenVar // doesnt know what hiddenVar is
}
}
.cpp
namespace Example
{
int hiddenVar;
}
Is there anyway to have a variable hidden within a namespace while giving a template function in the header access to it?
.h:
namespace Example
{
int * get_hiddenVar();
template< typename T >
void myFunc( const T& myT )
{
int * hiddenVarPtr = get_hiddenVar();
.. do something with *hiddenVarPtr
}
}
.cpp
namespace Example
{
int hiddenVar=0;
int * get_hiddenVar()
{
return &hiddenVar;
}
}
You cannot do this directly, but you can use a function. Since hiddenVar does not depend on the template parameters, you can do this:
.h
namespace Example
{
void Function(); // Use the right function prototype here, of course,
// as long as it does not depend on T
template<typename T>
void myFunc(const T& myT)
{
//...
Function();
//...
}
}
.cpp
namespace Example
{
int hiddenVar;
void Function()
{
// Do something with hiddenVar
}
}
If your use of hiddenVar depends on T, of course, you are out of luck.
Put it in a nested namespace called 'Details' and stop worrying.
'Hiding' a variable using namespaces and private etc are not security-constructs, but there to facilitate better code.
Related
Nutshell version: Why can't I define a template specialization (of a std-lib type) that's only useful in the current compilation unit in an anonymous namespace inside that compilation unit / cpp file?
Longer version:
I have a type that's only a quick helper inside one cpp file, let's call it struct Helper. Because it's only used in that compilation unit, it's declared and defined in an anonymous namespace inside the cpp.
Because I want an std::unordered_set<Helper>, I have to specialize std::hash. When I now try to define it inside the same anonymous namespace, I get a C2888 'std::hash<'anonymous-namespace'::Helper>': symbol cannot be defined within namespace 'anonymous-namespace'. Why is that?
I tried adding a using namespace std and similar things inside the AN, too, but to no avail.
/* This doesn't work */
namespace
{
struct Helper
{
int member1;
bool member2;
};
using namespace std;
template<>
struct std::hash<Helper>
{
size_t operator()(const Helper& helper) const
{
return 12345; /* how it's really generated is irrelevant here */
}
};
}
Of course, I can just put the specialization outside the AN, and it works. I just want to understand why it doesn't while it's inside it!
/* This works, but why doesn't the other? */
namespace
{
struct Helper
{
int member1;
bool member2;
};
}
template<>
struct std::hash<Helper>
{
size_t operator()(const Helper& helper) const
{
return 12345; /* how it's really generated is irrelevant here */
}
};
A symbol belonging to namespace std must be defined in a namespace that encloses std which means that you'll have to define it in the global namespace.
Here's an example from C2888:
namespace M {
namespace N {
void f1();
void f2();
}
void N::f1() {} // OK: namspace M encloses N
}
namespace O {
void M::N::f2() {} // C2888 namespace O does not enclose M
}
[temp.expl.spec/9] from the C++20 draft:
A template explicit specialization is in the scope of the namespace in which the template was defined. [ Example:
namespace N {
template<class T> class X { /* ... */ };
template<class T> class Y { /* ... */ };
template<>
class X<int> { /* ... */ }; // OK: specialization in same namespace
template<>
class Y<double>; // forward-declare intent to specialize for double
}
template<>
class N::Y<double> { /* ... */ }; // OK: specialization in enclosing namespace
template<>
class N::Y<short> { /* ... */ }; // OK: specialization in enclosing namespace
— end example ]
This question got me wondering whether it is ever useful/necessary to fully qualify class names (including the global scope operator) in an out-of-class member function definition.
On the one hand, I've never seen this done before (and the syntax to properly do so seems obscure). On the other, C++ name lookup is very non-trivial, so maybe a corner case exists.
Question:
Is there ever a case where introducing an out-of-class member function definition by
ReturnType (::Fully::Qualified::Class::Name::MemberFunctionName)(...) { ... }
would differ from
ReturnType Fully::Qualified::Class::Name::MemberFunctionName(...) { ... } (no global scope :: prefix)?
Note that member function definitions must be put into a namespace enclosing the class, so this is not a valid example.
A using-directive can cause Fully to be ambiguous without qualification.
namespace Foo {
struct X {
};
}
using namespace Foo;
struct X {
void c();
};
void X::c() { } // ambiguous
void ::X::c() { } // OK
It's necessary if one is a masochist and enjoys writing stuff like this
namespace foo {
namespace foo {
struct bar {
void baz();
};
}
struct bar {
void baz();
};
void foo::bar::baz() {
}
void (::foo::bar::baz)() {
}
}
One can of course write the second overload as foo::foo::bar::baz in global scope, but the question was whether or not the two declarations can have a different meaning. I wouldn't recommend writing such code.
If a using directive is used then there can be a confusing code.
Consider the following demonstrative program
#include <iostream>
#include <string>
namespace N1
{
struct A
{
void f() const;
};
}
using namespace N1;
void A::f() const { std::cout << "N1::f()\n"; }
struct A
{
void f() const;
};
void ::A::f() const { std::cout << "::f()\n"; }
int main()
{
N1::A().f();
::A().f();
return 0;
}
So for readability this qualified name
void ::A::f() const { std::cout << "::f()\n"; }
shows precisely where the function is declared.
So for some reason I have experienced the behavior that adding a namespace to my .h and .cpp files for a set of functions breaks my linker. I'm using Visual Studio 2012. Here's my scenario (simplified)
functions.h
int functionA();
int functionB();
functions.cpp
#include "functions.h"
int functionA() { return 0; }//we could pretend there's actual code here
int functionB() { return 0; }//we could pretend there's actual code here
and the actual useage of it is in some cpp file thusly:
pointers.h
#include "functions.h"
class GetPointers
{
public:
typedef int (*FunctionPointer)(void);
static FunctionPointer funcPointerA() { return &functionA; }
static FunctionPointer funcPointerB() { return &functionB; }
};
Well that's all fine and dandy. I can call the static method of GetPointers and get a function pointer which works. Everythings been tested and everything is happy. Now I thought I would simply add some namespaces to make sure I don't have any problems again in the future. So I simply modify the three code files to use namespaces. What happens is a link error which refers to the function funcPointerA() and funcPointerB() of the GetPointers class, with the full namespace name to functionA and functionB.
functions.h
namespace fun {
int functionA();
int functionB();
}
functions.cpp
#include "functions.h"
using namespace fun;
int functionA() { return 0; }//we could pretend there's actual code here
int functionB() { return 0; }//we could pretend there's actual code here
and the actual useage of it is in some cpp file thusly:
pointers.h
#include "functions.h"
namespace fun {
class GetPointers
{
public:
typedef int (*FunctionPointer)(void);
static FunctionPointer funcPointerA() { return &functionA; }
static FunctionPointer funcPointerB() { return &functionB; }
};
}
I don't get a build error, only a link error about fun::functionA and fun::functionB. Is there something implicitly wrong with using function pointers from namespaces?
The problem is that your definitions:
int functionA() { return 0; }
int functionB() { return 0; }
are in the global namespace; so they declare new functions there rather than define the functions declared in namespace fun.
The best fix is to qualify the names in the definitions:
int fun::functionA() { return 0; }
int fun::functionB() { return 0; }
This is preferable to putting the definitions inside the namespace, since it gives a compile-time check that the functions match their declarations.
goals:
1. store constants with their assignments in a header
2. keep constants in a namespace (without using #define)
3. allow constants to be whatever precision is needed for the app
I am trying to keep all constants for my header only library in the same namespace. I decided to do away with #defines and do things the right way, such as using:
namespace studio
{
namespace constant
{
const char* WHITE_SPACE = "\n\r\t ";
}
}
The hope is to access this like so:
studio::constant::WHITE_SPACE
This is all fine and good, from what I have gathered, doing it this way creates one of these for each translation unit, potentially to be optimized down to a single instance during linking. Even if it is not optimized like that, it is probably okay in this case.
The trouble comes when I want to add other types besides const char * as constants. For example, say I want to allow a float type (double or float) as a constant, but I would like to do it as a template so I don't have to do something like:
namespace studio
{
namespace constant
{
const char* WHITE_SPACE = "\n\r\t ";
const float PI_FLOAT = 3.141592653589793;
const double PI_DOUBLE = 3.141592653589793;
}
}
So I tried using a templated class instead of a namespace, with static functions which return the static constant like so:
namespace studio
{
template <class FloatType = float>
class constant
{
public:
static const char* white_space_chars() {
static const char* whiteSpaceChars = "\n\r\t ";
return whiteSpaceChars;
}
static const FloatType pi() {
static const FloatType _pi = 3.141592653589793;
return _pi;
}
}
}
This would then be accessed this way: studio::constant<float>::pi()
But now I have the problem where I have to supply a template parameter if I want one of my const chars even though they have nothing to do with floats, they must be accessed like so:
studio::constant<float>::white_space_chars()
because
studio::constant::white_space_chars()
does not work, even though I specified a default template parameter, apparently that only works for classes. C++ does not allow defaults on function templates.
So now the only way I can see to get around this is to have studio::constant_char, studio::constant_float, studio::constant_int, etc. That is ridiculous, right?
Really all I want is to have my defines in a namespace...
Do you know a better way to do what I am trying to do, where variables of different types can be used template like in the studio::constant namespace without forcing the user of the library to specify the type for each template parameter? Preferably not using C++11 to be more backward compatible.
Move the template onto the static methods that actually use it:
namespace studio
{
class constant
{
public:
static const char* white_space_chars() {
return "\n\r\t ";
}
template <class FloatType = float>
static const FloatType pi() {
return FloatType(3.141592653589793);
}
};
}
Then you can do this:
float flt_pi = studio::constant::pi();
double dbl_pi = studio::constant::pi<double>();
I suppose this could be done by having an override-able define such as:
#ifndef STUDIO_FLOAT_TYPE
typedef float STUDIO_FLOAT_TYPE;
#endif
namespace studio
{
namespace constant
{
const char* WHITE_SPACE = "\n\r\t ";
const STUDIO_FLOAT_TYPE PI = 3.141592653589793;
}
}
Which would allow the user to override the float type before including the library header. At least there's only one define and it still has a default.
Because surely a define like this would be used in other headers, I suppose it might be nice to keep all the customizable defines in a single header that all the individual library headers refer to.
For future reference, in C++14 you can do:
template <typename T>
const T PI = T(3.141592653589793);
See variable templates.
As an example:
// header.h
namespace constant
{
template <typename T>
constexpr T PI = T(3.141592653589793);
}
void foo();
// foo.cpp
#include <iostream>
#include "header.h"
void foo() {
std::cout << constant::PI<int> << std::endl;
}
// main.cpp
#include <iostream>
#include "header.h"
int main()
{
std::cout << constant::PI<float> << std::endl;
foo();
}
This gives the output:
3.14159
3
Is it legal to define the implementation of a function or class members outside the unnamed (anonymous) namespace they've been defined inside.
My compiler accepts it but I want to be sure it's legal
e.g.
////////////////
// foo.cpp
namespace {
struct X
{
void foo(int x);
};
}
// Is this legal?
void X::foo(int x)
{
}
The reason is I would like to avoid the unnecessary indentation imposed by our uncrustify formatting
It is really no different than the following, which is totally legit:
namespace ns {
struct s {
void f();
};
}
using namespace ns;
void s::f() { }
The names from the named namespace are brought into the global namespace and thus definitions can be provided for them there. The only difference with the unnamed namespace is that it has no name (really, it has some unique, unutterable name) and the using namespace is implicit.
#include <iostream>
using namespace std;
namespace
{
struct X
{
X(int);
int x_;
};
}
X::X(int x) : x_(x) {}
int main()
{
X x(5);
cout << x.x_ << "\n";
return 0;
}
Compiles (and runs) under gcc 4.6.0
Yes. It's perfectly legal. The difference an unnamed namespace makes is that, the content of the namespace is available only within the file it's declared. If it's in .h file then, it will be added to all the subsequent .cpp file and every .cpp file will have a unique copy of the contents of the namespace.
In fact it's a better way to declare a global static variable. Now see, what kind of difference it will make:
namespace {
struct X
{
void foo(int x);
};
int i; // declare this global variable
}
If you put this code inside a header file then, wherever that header file is #includeed, all those .cpp file will have a different copy of int i; inside them. Changing the value of i in one .cpp file doesn't affect the other .cpp file.
Moreover, it will not give linker error for multiple definitions, since it's in unnamed namespace.
Edit: To evaluate it more, define the namespace as following:
// x.h
namespace
{
struct X
{
void foo(int x)
{
static int c; // static inside the function
cout<<"a = "<<(c++)<<endl;
}
};
}
Now #include this header file in 2 different .cpp files. In both of them try to call foo() with object of X. It will print:
a = 0
a = 0
Which means that X::foo() in both the .cpp files are different. If you give the namespace a name and repeat the same thing, it will output
a = 0
a = 1
Thus unnamed namespace creates a different copy for each translation unit.
It's legal in your scenario, but in one scenario, it will cause compiler ambiguous error.
In case have another class in X.h:
// X.h
struct X
{
void foo(int x) { }
};
And in foo.cpp, need to use the X defined in X.h
////////////////
// foo.cpp
#include "X.h"
namespace {
struct X
{
void foo(int x);
};
// use the X declared in anonymous namespace
void test()
{
X x;
x.foo(3);
}
}
// reference to 'X' is ambiguous
void X::foo(int x)
{
}
void otherFunction()
{
// Use struct X in X.h
::X x;
x.foo(3);
}
if leave the implementation code out of the anonymous namespace, compiler complains ambiguous. If move the implementation code inside anonymous namespace, it works fine.