I could not find the definition of Time::Location.load?(string, Array(String) from https://github.com/crystal-lang/crystal/blob/7fb783f7afec0a199d6f22ef78aae0f45517068a/src/time/location.cr#L343
(Crystal 0.25.0)
Is it a "magic" function outside of the .cr source files?
Related
According to Why can't I multi-declare a class
class A; is a declaration while
class A { ... } is a definition
Typically, in header files, we define the class and we implement its member functions in the .cpp. But wouldn't defining classes in the header file violate the One Definition Rule?
According to https://www.learncpp.com/cpp-tutorial/89-class-code-and-header-files/
Doesn’t defining a class in a header file violate the one-definition rule?
It shouldn’t. If your header file has proper header guards, it
shouldn’t be possible to include the class definition more than once
into the same file.
Types (which include classes), are exempt from the
part of the one-definition rule that says you can only have one
definition per program. Therefore, there isn’t an issue #including
class definitions into multiple code files (if there was, classes
wouldn’t be of much use).
While the first part is obviously true, header guards will prevent multiple definitions in the same file, but I am confused about the second part of the answer that addresses my question.
If a header file has a definition of a class, for example ThisClass, and that header file is included in two other files for example a.cpp and b.cpp. Why wouldn't it violate the One Definition Rule? If a ThisClass object is created in either file, which definition would be called?
If a header file has a definition of a class, for example ThisClass, and that header file is included in two other files for example a.cpp and b.cpp. Why wouldn't it violate the One Definition Rule?
Because, as you quoted, the one definition rule specifically allows for this.
How can it? Read on…
If a ThisClass object is created in either file, which definition would be called?
It doesn't matter, because the definitions are required to be absolutely, lexically identical.
If they're not, your program has undefined behaviour and you can expect all manner of weirdness to ensue.
Based on what I'm reading, it might be important to use Wikipedia's brief explanation of what the One Definition Rule actually is:
The One Definition Rule (ODR) is an important rule of the C++ programming language that prescribes that objects and non-inline functions cannot have more than one definition in the entire program and template and types cannot have more than one definition by translation unit.
This means that when the program is compiled, there can be one, and only one definition of a function or object. This might be confusing, however a class or type shouldn't be thought of as objects, they're really just blueprints for an object.
In your question, I think there's a misunderstanding of what #include does and how the ODR applies to classes. When the program is compiling, the .cpp files look to their #include'd class definitions as a way to link together, that is, the class.h blueprint must know where to look when calling it's member functions. Having multiple #include's of the same class.h is not the same as having multiple definitions of class.h, and thus, it cannot violate the One Definition Rule.
It is okay to have a class defined in a header file because the compiler treats the functions declared in the class in such a case as an inline functions.
So there are two options to happen when you call this class functions:
Or it wiil inline the function calls and in such a case there is no problem at all of multiple definition.
Or it wont inline them and in such a case he will create the symbols related to the functions as weak symbols. Then the linker will choose one of the symbols to be the symbol representing the function.
Of course if there will be different defintions in two or more cpp files there will be undefined behaviour.
To make a function inline should I add the keyword inline in function prototype or in function definition or should I add the inline keyword both in function declaration and function definition.
If you already have a declaration and definition, you don't need to add inline anywhere. The inline keyword is not a magical optimization incantation, but more of a linkage specifier.
An inline function must be defined in every translation unit it's used in. How can it be defined there? Simple, it's put in header:
// foo.h
inline void foo() {}
But wait, I hear you say, won't putting it in header cause a multiple definitions error? Not when it's marked inline, that's why I called it more of a linkage specifier. The inline specifier tells the compiler that all those multiple definition it sees are the same. So it may in fact use any one of them. Or it may inspect the function body and choose to do code inlining, but it doesn't have to.
The primary purpose of the keyword is to allow those multiple definitions to appear inline, not to cause the function's code to be inlined. So again, if you have a definition in a cpp file and a declaration in a header, you don't need to do anything. If you have a utility you want to appear in a header, put it there - definition and all - and add the inline keyword.
How to make function inline:
To make any function as inline, start its definitions with the keyword “inline”.
From the article.
I'm working my way through a C++ tutorial, and in one of the articles on the preprocessor/header files the author creates 2 'header files' (not the technical term, of course), example.h and example.cpp. In example.h he puts the forward declarations for the functions and the header guard, and in example.cpp the actual body of the functions. Why is this? I tried putting the body of the function in the example.h file and it worked just fine, so why does he put it separately? Is it customary, or does it pose problems in bigger problems? Or what?
Can someone please enlighten me on this...
C++ has a rule called the one-definition rule that says that every function needs to be defined once and only once (there are a few exceptions to this rule, but we'll ignore them for now.) The function prototype typically included in a header file is a declaration saying that the function exists, and the implementation in the .cpp file is the definition giving the code for the function.
If you put the definition of the function in a header file and then include the header file in multiple places, you'll get linker errors because you're breaking the one definition rule - each .cpp file that's compiled will have its own copy of the definition of the function. On the other hand, if you just put the declaration in the header and then put the definition in a single source file, then there's only one definition and nothing will break.
There are a few exceptions for the one definition rule. First, all inline functions are exempt from ODR, so you could potentially put function definitions in a header file if you mark all the functions inline, though this is generally not considered a good idea for all but the smallest functions. Second, template functions are exempt from the ODR, which (among other things) is one of the reasons you see template functions defined in headers.
Put the function body in example.h. Then, when you write a second .cpp file that also includes example.h, and link it with example.cpp, then you'll get a linker error. The linker will see 2 definitions of the function in example.h.
Becouse in the header file you only declare functions that is really important when you want to use a custom linking configuration. For example if a function is defined in a file object and is used in an another object the linker must have the same reference for this function to link the two different files.
I have a task:
To implement a template vector class (let's name it myvector). I need to use this class in multiple files in my project, so I've put it's declarations in "myvector.h" file, and implementation into "myvector.hpp" file, and then included "myvector.hpp" in "myvector.h" after all the declarations (as described there). However, I have one non-template function in "myvector.hpp". So when I include "myvector.h" file in main file, everything works fine. But when I include "myvector.h" in another one file ("bignum.cpp"), I get a linker error:
error LNK2005: "unsigned int __cdecl gerasimov_dmitry::calculate_capacity(unsigned int)" (?calculate_capacity#gerasimov_dmitry##YAII#Z) already defined in bignum.obj
I understand the causes - "bignum.h" code gets included both in main.cpp and in bignum.cpp file, so compiler doesn't know which one "calculate_capacity" function to use. So, my question is how to fix this situation.
You have to declare the function inline (or alternatively move the definition to a single translation unit).
The problem that you are facing is that if you define the function in the header, and include that header in more than one translation unit, the compiler will generate the function in all translation units.
When the linker tries to generate the program (or library) it finds that the function is defined multiple times and complains about it, as that is a violation of the ODR (One Definition Rule). By marking the function as inline the compiler will flag that function so that when the linker sees the multiple definitions instead of choking it will discard all but one of the definitions.
Non inline function defined in header file with guards
#if !defined(HEADER_RANDOM_H)
#define HEADER_RANDOM_H
void foo()
{
//something
}
#endif
Results in linker error : Already defined in someother.obj file
Making the function inline works fine but I am not able to understand why the function is already erroring out in first case.
If the header is included in more than one source file and the function is not marked as "inline" you will have more than one definition. The include guards only prevent multiple inclusions in the same source file.
You're violating the one definition rule. If you want to define a function directly in the header, you must mark it as inline -- that will allow the function to be defined multiple times. Also note that inline has no other meaning, particularly it doesn't force the compiler to inline calls (contrary to popular belief).
Since it is not inline, each translation unit will have its own copy of the function resulting in the function being defined multiple times.