I want to create a Commons.h file where I can put some shared info, constants, macros and helper functions.
This file has to be included in many part of my application.
If I create function with this syntax I get a Duplicate Symbol error:
int myFunction(int a){
//do something..
}
While if I add the static keyword I get no errors.
static int myFunction(int a){
//do something..
}
1) Is this a valid/right way to add helper functions to a project?
2) What happen exactly adding the static keyword at that definition?
Not really. You're creating a separate instance of the function
in every translation unit. What you should do is only declare
the function in the header:
extern int myFunction( int a );
and define it in a source file somewhere. (Note that the
extern above is optional, since it is implicit for all
function declarations, and it is usual to omit it. I add it
here only to stress the fact that you are declaring, and not
defining.)
If you use the keyword static before a function declaration, then you only can use this function inside the actual translation unit (.cpp, .c or .m), where it was defined.
So it is the opposite of the keyword extern, extern is the default storage class specifier for functions.
The use for a helper function is then wrong, because it doesn't even compile.
Instead you should declare the function in the helper file as extern. And use it without implementing it again. You can implement it once in the .c/.cpp/.m of the helper .h.
If you use a function as a helper function for other files, then it is good practice to use the extern keyword, even though it is not needed. It is a hint for programmers, this function is used somewhere else.
Related
I have a very small function that could be a macro, but anyway, I thought inline function would do exactly the same.
But nah, when I mark a function in a namespace as inline it is not visible by any other file that includes my module.
I tried it both with a static class and a namespace. No error when the function is declared or implemented, error in each reference, exactly as if the function was static.
Is there a way to have an inline function available for other files that include the file where my function is declared?
Let's say I have a module that handles some hardware stuff, and one of the functions is something like this:
bool getState(HWFlag flag)
{
return (State & flag) > 0
}
I know, it can be written as macro, but logically the function is a part of a bigger module. I would certainly used a macro in C, but it's C++ so I thought there might be a better way. But well, I obviously don't understand how it works.
BTW, shouldn't the compiler just inline it anyway so I shouldn't even care?
BTW2: Is making the module that mainly talks with C code a class with only static method a bad idea or does it have any use? That's how I made it initially but later decided to just make it a namespace to simplify the syntax a little. But in any case, if I use the inline keyword the function becomes private.
An inline function should be defined identically in every translation unit that uses it. So you should define your inline function exactly as you would a macro--in a header file that gets included by all of the files that need it.
I want to use extern keyword for class method in C++. I'm using Visual Studio 2019.
I want to force method inline, using __forceinline(without extern I will get unresolved external symbol). I don't want to put method implementation in this header file, I want put implementation in other .cpp file.
I noticed that method may be inlined automaticly without extern and __forceinline and when method's implementation in .cpp file. How can I force it?
Example code:
class Window {
public:
void Show();
};
That's ok!
class Window {
public:
__forceinline void Show();
};
Gets unresolved external symbol when I calls this function from other CPP.
With extern I gets:
screenshot
For simple functions extern __forceinline works fine:
screenshot
You cannot specify extern for a member function.
The standard clarifies this in [dcl.stc]/5:
The extern specifier can be applied only to the names of variables and functions. The extern specifier cannot be used in the declaration of class members or function parameters.
When you use extern, you say to the compiler that you declare a variable or a function, but without defining it. In the case of member functions, this is not needed: they can always be declared in a class body without being defined:
class A {
public:
void f(); // you can define it in which ever compilation unit (cpp) you want
};
...
// Else where...may be in another cpp
void A::f() {...}
The linker will resolve the symbols when needed.
The inline is not so useful
The standard in [dcl.inline]/2 says that inline is not guaranteed:
The inline specifier indicates to the implementation that inline
substitution of the function body at the point of call is to be
preferred to the usual function call mechanism. An implementation is
not required to perform this inline substitution at the point of call;
Furthermore, [dcl.inline]/6 explains that inline and defined eleswhere is not something meant to work well:
An inline function or variable shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case.
(odr says that all the definitions must be exactly the same definition each time)
(in every translation unit means in every cpp or the headers therein included)
On the other side, the global optimizer of some modern compilers is able to achieve similar performance effects than inlined functions, and this accross compilation units (cpp).
Implementation specific forceinline
MSVC 2019 uses inline carefully, making a cost/benefit analysis to decide whether or not to inline.
forceinline allows you to overrule the compiler's judgement. But it comes with all the requirements of the normal inline: so you need to have a definition of the function in the same compilation unit to get it work.
Two things:
You cannot declare a member function as extern. These already have external linkage.
For the compiler to inline a function or method, it has to be defined (as opposed to declared) in the header file. This is so that the compiler can see it when compiling code that calls the function.
So, just put the function body in the header file and drop the extern.
I don't want to put method implementation in this header file, I want put implementation in other .cpp file.
Sounds to me like you just want to have all declarations in one file like this:
This is your window.h- file:
class Window
{
public:
void Show();
};
To have the implementation in another file, you have to use the scope operator.
This is the other window.cpp- file, in which you have the actual implementation of the function:
#include "window.h"
Window::Show()
{
// Your implementation goes here
}
I hope I understood your question right and this helps.
I have a function which should be included in two different translation units (i.e. cpp files) from a common header.
I might use an anonymous namespace to have this function included in both TUs without conflicts but I'm wondering what would be the best way to accomplish this (static? I don't think global could work, multiple definitions)
If you want it to be the same function in every TU, use inline. That's exactly what inline is for: shared functions defined in headers.
In the admittedly-unlikely event that you want it to be a different function in every TU, use either an unnamed namespace or static. I don't think the standard gives an official view which one is preferred in C++, but you kind of get the impression it's the unnamed namespace.
Which one you want depends on why you're putting a function definition in a header file in the first place, and how you intend the header to be used.
You need to learn the difference between declaration of function and it's definition. Except of template and inline functions only function declaration should be in a header file, function definition should be in translation unit.
void foobar( int ); // this is function declaration, now you can call this function
// you can put it on your sources as many times as you want
void foobar( int param ) { // this is function definition, it should appear only once
...
}
If you want that the compiler would consider this function as a different function in each CU you can include its definition in an unnamed namespace. According to the C++ 2011 Standard entities declared in unnamed namespaces have internal linkage.
EXTERN(void) jpeg_fdct_8x4
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
Here, I had four questions:
What does the syntax Extern(Void) mean? That the return value is void? Is it a usual syntax?
I see in a third-party code non-class member functions with the static keyword, inline keyword, no keyword and extern keyword. I understand that static keyword limits the scope of the function to the file. What happens if I use "no keyword"? Do I have to use extern in other file to use that function or I can call the function directly from another file after specifying the function declaration?
Do I need extern in C++ only to call interface with C?
What is the default scope of inline functions?
EXTERN(n) is a preprocessor definition, to be found in jmorecfg.h:
#define EXTERN(type) extern type
So the above statement expands to
extern void ...
For a writeup of extern in C code, check out this answer.
What happens if I use "no keyword"?
In this case the scope is not limited. Non static, global functions have their name visible to the linker across all compilation units, which means you get name clashes if different modules use the same function names.
3) Do I need extern in C++ only to call interface with C?
You presumably refer to extern "C" {} which instructs the compiler to use C calling convention. Yes, you need this to invoke external C functions from C++.
4) What is the default scope of inline functions?
The same scope as if they weren't declared inline.
C++ is a case-sensitive language. The "extern" keyword is not the same as "EXTERN". It seems to be initializing a void function.
You can use functions from other source files without using the extern keyword. e.g. When you are writing a project, the IDE will always start debugging and compiling with the main() function. You can declare and call functions in other files without using extern.
code from google's v8 js engine, allocation.h:
template <typename T>
static void DeleteArray(T* array) {
delete[] array;
}
This is a function template (top level, not in any class).
But what the static keyword is for?
That it's a template is actually a side-issue.
It being static means the function is not visible outside of the file (but since it's in a header and headers are effectively part of the files that include them, that means outside of the file that includes the header; and each file that includes the header effectively has its own, identical but private version of the function).
From http://msdn.microsoft.com/en-us/library/s1sb61xd%28VS.80%29.aspx:
"When modifying a variable or function
at file scope, the static keyword
specifies that the variable or
function has internal linkage (its
name is not visible from outside the
file in which it is declared)."
See here fore more on what it means to have this in a header file:
C/C++: Static function in header file, what does it mean?
The static keyword gives the definition "internal linkage", which means it would be legal to give the name DeleteArray another meaning or a different definition in a different source file. (Just as is the case with static void f(); or static int i;.) But I can't imagine anyone would want to do that.
Use of static this way in C++ is deprecated. This declaration would probably be better without the static keyword, making it implicitly extern (and still inline). In that case, the linker would be allowed to combine any definitions of DeleteArray<T>(T*) for the same T from multiple objects, since they would be the same thing.
static functions (outside of a class) cannot be used outside the defining file. It's a holdover from C where there are no namespaces. I bet you'll find that DeleteArray() isn't called from another file, unless it's been redefined in that other file.