I have a number of templatic and inline functions defined in an header file (let's call it head.h). Currently, these functions use some global variables declared with extern in the same header and defined somewhere in one .cpp.
Everything works fine, but I would limit global variables scope only to the header where they are defined.
In other words every other .h or .cpp that includes my head.h wouldn't be able to see such globals.
Any way to achieve this result?
including header files just copies the content of the header file into the including cpp/h file. That means, you cannot really distinguish whether you do something in your header file or in a cpp/h file that includes your header file.
So, variables that are defined in a header file cannot be excluded. If they are in a cpp file and you would like to forbid extern, you could use an anonymous namespace:
namespace
{
int variable;
}
Best practice, obviously, would be to not use global variables at all. It is considered bad style for several reasons like readability, hard to determine dependencies, difficulties with testing, a really bad chance of extending your software and so on. So, you might reconsider this kind of architecture for your next project if refactoring is not an option here.
One way would be to put a class around it instead of a namespace, making all functions public static methods of that class and the global variables private static variables.
i.e.:
head.h:
class A
{
public:
template <typename T> static void MethodA(T const &value)
{
//...
}
inline static void MethodB(int a, int b)
{
// ...
}
private:
static int x;
static std::string y;
};
head.cpp:
int A::x = 0;
std::string A::y;
EDIT:
Another alternate method would be to define the globals as private static variables in a class and make all functions that are allowed to use them friend functions:
head.h:
template <typename T> void FunctionA(T const &value);
void FunctionB(int a, int b);
class Vars
{
friend template <typename T> void FunctionA(T const &value);
friend FunctionB(int a, int b);
private:
static int x;
static std::string y;
};
template <typename T> void FunctionA(T const &value)
{
// ...
// ... A::x ...
// ...
}
inline void FunctionB(int a, int b)
{
// ...
// ... A::y ...
// ...
}
head.cpp:
int A::x = 0;
std::string A::y;
No, it is not possible.
If you declare some variable as extern in a header1.h - this variable will be available in any other headers which include header1.h.
Related
Using C and plain functions in C++, I can prevent the functions' symbols to be exported by using static keyword:
static int foo(int a, int b) { /* ... */ }
But in a class, defining a function as static has a completely different meaning. Is there a way to ensure the compiler that my whole class will be used only within module, and there is no need to export any of its methods' symbols?
Use an anonymous namespace.
namespace
{
class C
{
C() {}
void f() {}
};
void f();
}
class ExportedClass
{
ExportedClass() {}
void f() {}
};
void exportedFunction() {}
As you can see, you should do this for normal functions, too. The usage of static for this is discouraged.
You can use the anonymous namespace. For example,
// file foo.cc
namespace {
int symbol1 = 0;
struct auxiliary { /* ... */ } symbol2;
}
void foo(int x)
{
// uses symbol1 and symbol2
}
when symbol1 and symbol2 are not 'visible'.
Depending on what you want and why you are doing it you could move the class into the .cpp file. This works for example if you are implementing a library. Have a look at the discussion at Putting class declaration in .cpp file
To be more specific your class should go in it's own separate translation unit away from main and away from classes outside of your module.
I want to only have 2 extern C functions, which are how to interact with the API. Then inside the static .lib I want to have my class that does all the work. But it shouldnt be visible to the outside.
I can do it with just pure C functions by declaring them static inside a compilation unit, but how do I do it with a class ?
If I understand your question well:
you want to create a static library presenting only two functions to the outside world
but the internals of this library should be based on a class you want to hide from outside world.
you know how to do hiding internals in classic c (i.e. using auxiliary static functions and static variables) but you don't see how to do with classes
If this is the case, the trick is simply to use an unamed namespace:
In your library source you would have something like this:
namespace { // anonymous
class U { // class visible only to the library
public:
int y;
U() :y(0) { cout << "U\n"; }
void mrun() { y++; }
};
}
void f() {
U x;
...
}
You may then use your library from outsilde world:
extern void f(); // declare the function (in a header)
f(); // invoke the function
Even if the auxiliary class would be declared in the outside world:
class U { public: int y; U(); void mrun(); };
It would not be able to used and linking errors would be generated if it would be tempted to use U. This is because unnamed namespaces are unique to each compilation unit.
If you use the same kind of solution but without the anonymous namespace, the auxiliary class would be visible and the link would succeed.
Perhaps you could mirror the class's API using C functions a bit like this:
class Cpp
{
int i = 0;
public:
int get_i() { return i; }
void set_i(int i) { this->i = i; }
};
// C code has a void* as a handle to access
// the correct instance of CPP
extern "C" void* new_Cpp()
{
return new Cpp;
}
extern "C" void delete_Cpp(void* cpp)
{
delete reinterpret_cast<Cpp*>(cpp);
}
extern "C" int Cpp_get_i(void* cpp)
{
return reinterpret_cast<Cpp*>(cpp)->get_i();
}
extern "C" void Cpp_set_i(void* cpp, int i)
{
return reinterpret_cast<Cpp*>(cpp)->set_i(i);
}
I've been always avoiding the following in C++ (which I believe is C++03 used in VS 2008) but now I'm curious if it's possible to do this? Let me explain it with the code.
//Definitions.h header file
//INFO: This header file is included before CMyClass definition because
// in contains struct definitions used in that class
struct MY_STRUCT{
void MyMethod()
{
//How can I call this static method?
int result = CMyClass::StaticMethod();
}
};
then:
//myclass.h header file
#include "Definitions.h"
class CMyClass
{
public:
static int StaticMethod();
private:
MY_STRUCT myStruct;
};
and:
//myclass.cpp implementation file
int CMyClass::StaticMethod()
{
//Do work
return 1;
}
In this case, you would need to move the implementation of MY_STRUCT::MyMethod outside the header file, and put it somewhere else. That way you can include Definitions.h without already having CMyClass declared.
So your Definitions.h would change to:
struct MY_STRUCT{
void MyMethod();
};
and then elsewhere:
void MY_STRUCT::MyMethod()
{
int result = CMyClass::StaticMethod();
}
Suppose there is a global variable in a translation unit. It is constant, but not compile time constant (it is initialized with an object that has a non constexpr constructor). It is declared static since it should be private to the translation unit. Obviously, that global is defined in the .cpp file. However, now I have added a method template to that file that needs the global variable. Since it is a method that will be used by other translation units, it has to be put into the header. However, once it is in the header it can no longer access the global variable. What is the best practice to solve this problem?
There is, but a little tricky way to achieve your goals:
The variable is private, available only to some elements.
Your function template can access it.
Use private static variable in a class defined in header, and make your function/class templates friend of this class.
YourFile.h
class PrivateYourFileEntities {
private:
static const int SomeVariable;
// ... other variables and functions
template <class T>
friend class A;
template <class T>
friend void func();
// the rest of friends follows
};
template <class T>
void A<T>::func() {
int a = PrivateYourFileEntities::SomeVariable;
}
template <class T>
void func() {
int a = PrivateYourFileEntities::SomeVariable;
}
YourFile.cpp
const int PrivateYourFileEntities::SomeVariable = 7;
Put the method declaration into .h file and method body into .cpp file like:
.h file:
#include <iostream>
void myfunc1();
void myfunc2();
.cpp file:
#include "myheader.h"
static int myglobalvar=90;
void myfunc1()
{
cout << myglobalvar << endl;
}
void myfunc2()
{
cout << "Oh yeah" << endl;
}
suppose I have a file alpha.h:
class Alpha {
public:
template<typename T> void foo();
};
template<> void Alpha::foo<int>() {}
template<> void Alpha::foo<float>() {}
If I include alpha.h in more than one cpp file and compile with GCC 4.4, it complains there are multiple definitions of foo<int> and foo<float> across multiple object files. Makes sense to me, so I change the last two lines to:
template<> extern void Alpha::foo<int>() {}
template<> extern void Alpha::foo<float>() {}
But then GCC says:
explicit template specialization
cannot have a storage class
ok... so how am I supposed to do this correctly? I'm worried that C++ doesn't allow what I'm trying to do in the first place, in which case is there a good idiom that will accomplish the same thing?
use inline keyword
template<> inline void Alpha::foo<int>() {}
alternatively, provide implementation in separate cpp file
You can forward declare as well as the inline option:
// .h
template<> void Alpha::foo<int>();
//.cpp
template<> void Alpha::foo<int>() {}
From the ODR point of view, a fully (explicitly) specialized template is no longer a template, so it is subject to the same ODR principles as a non-template entity of the same kind. (There are some exceptions from that rule, I believe, but it is good enough for our purposes).
In your case, for ODR purposes a fully specialized function template is an ordinary function. So, as an ordinary function it should be declared in the header file and defined in one and only one implementation file.
No separate declaration or inline keywork is required. PF below working code.
#include<iostream>
class temp
{
public:
template <class T>
T add1(T a, T b)
{
return (a + b);
}
};
template<>
std::string temp::add1<std::string>(std::string aa, std::string bb)
{
return aa+bb;
}
int main()
{
temp *tc = new temp();
std::cout << tc->add1<float>(5.7, 4.5) << std::endl;
std::cout << tc->add1<std::string>("my ","program") << std::endl;
}
output is :
10.2
my program