Hi,
Where should I put typedef that is used in several header files? Putting it in each file causes multiple declaration error, and yet each header file requires a declaration. Should I play around with name spaces?
Thx
Hi,
Where should I put typedef that is used in several header files? Putting it in each file causes multiple declaration error, and yet each header file requires a declaration. Should I play around with name spaces?
Thx
Place it in a header that is included by the other headers; remember to use inclusion guards.
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
And post your code if you still run into issues.
Last edited by Guest; 10-11-2019 at 06:05 AM. Reason: too slow ;)
Yes, this works if I put implementations in the header, but i would like to have a clean header file and a cpp file with function bodies. The below pattern currently produces an mt19937 error:
So the header would read (without guards, for brevity):
Let the header be called dice.h. I have this in dice.cpp:Code:#include <random> #include <vector> typedef std::mt19937 rngT; rngT rng; const std::vector<int> Roll_DX_Ntimes(rngT& r, const int X, const int N);
and in the mainCode:#include <random> #include <vector> #include "dice.h" const std::vector<int> Roll_DX_Ntimes(rngT& r, const int X, const int N) { // implementation }
Code:#include <random> #include <vector> #include "dice.h"
You're initializing an object in the header. That is the problem, not the typedef.
Code:#include <random> #include <vector> typedef std::mt19937 rngT; rngT rng; // ← this is the issue const std::vector<int> Roll_DX_Ntimes(rngT& r, const int X, const int N);
Last edited by Guest; 10-11-2019 at 08:38 AM. Reason: formatting
OK, I missed that! So where should the second line go, given that the type is used in practically the whole program, i.e. certainly downstream of dice.h. Does it need to stay global?
Put it as close to your use as is sensible, e.g.
Avoid global variables except for edge cases (which are rare).Code:int main() { rngT rng; const auto result = Roll_DX_Ntimes(rng, 1, 2); }
Edit: If you want to share the rng, see if passing it to the call chain in main is feasible. If you think you cannot avoid it, then do:
Code:// dice.h extern rngT rng; // dice.cpp rngT rng;
Last edited by Guest; 10-11-2019 at 09:10 AM. Reason: f*** this slow forum
You could use
for your header file containing your typedefs, function declarations and definitions, etc and then include in multiple files without any problems I believe.Code:#pragma once
You should be aware that as there is increasing support for templates and declaring stuff to be inline, it has also become more common for libraries (and hence C++ programs in general) to become "header-only", as in containing template classes/functions and inline functions and even inline variables defined in headers, with a much smaller amount of code going into source files.Originally Posted by serge
Yes, you could, but no, you shouldn't. #pragma once is non-standard (which admittedly is a feature of #pragma: a standard way to enable non-standard stuff), and while compilers tend to support it these days, there's no guarantee that it will do the right thing on all compilers for the various ways C++ source code could be stored and compiled on file systems. On the other hand, inclusion guards will always do the right thing... as long as they are unique (hence techniques like including a timestamp in the inclusion guard name). Eventually we may see both of them phased out should modules become a reality in C++20 and continue to see adoption after that.Originally Posted by Zeus_
In this case though, neither a header inclusion guard nor #pragma once will help because their purpose is to avoid violating the one definition rule for entities that must not be defined more than once within a translation unit (source file + included headers). As Guest pointed out in post #5, the issue is that an object was defined in a header at namespace scope, so its name has external linkage. This means that when the header is included in multiple translation units, the name refers to the same object in each of the transaltion units, hence the object is defined multiple times across the program. This violates the one definition rule for such objects: these must be defined once across the entire program, not merely once per translation unit.
Speaking of the one definition rule, I was mistaken about the typedef: it is explicitly listed as a declaration that is not a definition, so it does not fall under the one definition rule, i.e., as long as you don't have conflicting declarations, you can declare the typedef multiple times in the same scope within a translation unit without violating the one definition rule, hence the use of inclusion guards would not strictly be necessary for a header consisting entirely of typedef declarations.
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
To follow up on templates. Putting this function in the header (along withandCode:#include <iostream>)Code:#include <vector>
also does not compile. But why?Code:template <typename T> void PrintVector(const std::vector<T>& vector) { for (const auto& element : vector) std::cout << " " << vector; }
As for the guards, I putting both the regular guards and pragma each header file. I believe there is no harm in putting both in.
You probably want to print element instead of vector.
Btw, instead of just saying "it does not compile", post the compile error.
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
Yes, I made a cut-and-paste error - vector should be element. The problem that I have is this:
1. Header (utilities.h)
2. Implementation (utilities.cpp)Code:#ifndef UTILITIES_H #define UTILITIES_H #pragma once #include <iostream> #include <vector> template <typename T> void PrintVector(const std::vector<T>& vector); #endif
3. MainCode:#include "utilities.h" template <typename T> void PrintVector(const std::vector<T>& vector) { for (const auto& element : vector) std::cout << ";" << element; }
4. Linker-error (in Microsoft VS):Code:#include "utilities.h"
Code:Severity Code Description Project File Line Suppression State Suppression State Error LNK2019 unresolved external symbol "void __cdecl PrintVector<int>(class std::vector<int,class std::allocator<int> > const &)" (??$PrintVector@H@@YAXABV?$vector@HV?$allocator@H@std@@@std@@@Z) referenced in function _main mysim D:\devvs\mysim\main.obj 1
Have you added utilities.cpp to your project as a dependency, so that it gets linked? (I don't know how VS works)
Oh, you're using templates! Sorry, totally missed that. As laserlight said, move the implementation into the header.