Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ set(APP_SOURCES
"src/core/basics/Operations.cpp"
"src/core/basics/TypeQualifier.cpp"
"src/core/basics/ControlFlow.cpp"
"src/core/linkage/Internal.cpp"
"src/core/linkage/Linkage.cpp"
"src/core/linkage/External.cpp"
"src/core/linkage/sharing/Sharing.cpp"
"src/core/linkage/sharing/external/constants.cpp"
"src/core/datatypes/Fundamental.cpp"
"src/core/datatypes/CArray.cpp"
"src/core/datatypes/CReferences.cpp"
Expand Down
28 changes: 0 additions & 28 deletions src/core/basics/Linkage.cpp

This file was deleted.

3 changes: 3 additions & 0 deletions src/core/basics/TypeQualifier.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// cppcheck-suppress-file [unreadVariable]
// A function declared constexpr is implicitly an inline function.
// A static member variable (but not a namespace-scope variable) declared constexpr is implicitly an inline variable.

#include <iostream>
using namespace std;

Expand Down
21 changes: 21 additions & 0 deletions src/core/linkage/External.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "External.h"
#include <iostream>

namespace External { // We must define the variable inside the same namespace as its extern declaration;
// otherwise the linker cannot find the correct symbol.

// 1. Non-Static global variable/ function
int nonStaticVar{1};
void nonStaticFnc() {
std::cout << "nonStaticFnc\n";
}

// 2. Extern Const/constexpr
extern const int EXTERN_CONST_VAR{200};

// 3. Namespaces
namespace Name {
int namespaceVar = 123; // Định nghĩa
}

} // namespace External
9 changes: 9 additions & 0 deletions src/core/linkage/External.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace External {
// 3. Inline const/constexpr in header file
inline const int INLINE_CONST_VAR{100};
constexpr int CONSTEXPR_VAR{500};

namespace Name {
extern int namespaceVar;
}
} // namespace External
21 changes: 21 additions & 0 deletions src/core/linkage/Internal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <iostream>

namespace Internal { // We must define the variable inside the same namespace as its extern declaration;
// otherwise the linker cannot find the correct symbol.

// 1. Static global variable/ function
static int g_internal{42};
static void func_internal() {
std::cout << "func_internal\n";
}

// 2. Const/constexpr
const int c_internal{100};
constexpr int ce_internal{100};

// 3. Anonymous namepsace
namespace {
int ns_internal{100};
}

} // namespace Internal
51 changes: 51 additions & 0 deletions src/core/linkage/Linkage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// cppcheck-suppress-file [unreadVariable]
#include <iostream>
#include "External.h"
using namespace std;

namespace Internal {

extern int g_internal; // ERROR: g_internal not visible outside Internal.cpp
extern int ce_internal; // ERROR: g_internal not visible outside Internal.cpp
extern int c_internal; // ERROR: g_internal not visible outside Internal.cpp
extern int ns_internal; // ERROR: g_internal not visible outside Internal.cpp

void func_internal(); // ERROR: helper not visible outside Internal.cpp

void run() {
// std::cout << g_internal;
// std::cout << ce_internal;
// std::cout << c_internal;
// std::cout << ns_internal;
// func_internal();
}
} // namespace Internal

namespace External {
// use extern without initliaizer/forward declaration to access the external global variable/function
extern int nonStaticVar;
void nonStaticFnc();
extern const int EXTERN_CONST_VAR;

void run() {
std::cout << nonStaticVar << "\n";
std::cout << EXTERN_CONST_VAR << "\n";
std::cout << INLINE_CONST_VAR << "\n";
std::cout << CONSTEXPR_VAR << "\n";
std::cout << Name::namespaceVar << "\n";
nonStaticFnc();
}

} // namespace External

struct LinkageAutoRunner {
LinkageAutoRunner() {
cout << "\n"
<< "\n"
<< "Linkage\n";
Internal::run();
External::run();
}
};

static LinkageAutoRunner autoRunInstance;
39 changes: 39 additions & 0 deletions src/core/linkage/sharing/Sharing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// cppcheck-suppress-file [unreadVariable]
#include <iostream>
using namespace std;

#include "external/constants.h"
#include "inline/constants.h"
#include "internal/constants.h"

namespace InternalWay {
void run() {
std::cout << InternalConstants::avogadro << "\n";
}
} // namespace InternalWay

namespace ExternalWay {
void run() {
std::cout << ExternalConstants::avogadro << "\n";
}
} // namespace ExternalWay

namespace InlineWay {
void run() {
std::cout << InlineConstants::avogadro << "\n";
}
} // namespace InlineWay

struct SharingGlobalConstantsAcrossMultipleFilesngAutoRunner {
SharingGlobalConstantsAcrossMultipleFilesngAutoRunner() {
cout << "\n"
<< "\n"
<< "SharingGlobalConstantsAcrossMultipleFiles\n";

InternalWay::run(); // prefer 2
ExternalWay::run();
InlineWay::run(); // prefer 1
}
};

static SharingGlobalConstantsAcrossMultipleFilesngAutoRunner autoRunInstance;
9 changes: 9 additions & 0 deletions src/core/linkage/sharing/external/constants.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "constants.h"

namespace ExternalConstants
{
// We use extern to ensure these have external linkage
extern constexpr double pi { 3.14159 };
extern constexpr double avogadro { 6.0221413e23 };
extern constexpr double myGravity { 9.2 }; // m/s^2 -- gravity is light on this planet
}
22 changes: 22 additions & 0 deletions src/core/linkage/sharing/external/constants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// global constants as external variables:

// Advantages:
// Works prior to C++16.
// Only one copy of each variable is required.
// Only requires recompilation of one file if the value of a constant changes.
// Downsides:
// Forward declarations and variable definitions are in separate files, and must be kept in sync.
// Variables not usable in constant expressions outside of the file in which they are defined.

#ifndef ECONSTANTS_H
#define ECONSTANTS_H

namespace ExternalConstants {
// Since the actual variables are inside a namespace, the forward declarations need to be inside a namespace as well
// We can't forward declare variables as constexpr, but we can forward declare them as (runtime) const
extern const double pi;
extern const double avogadro;
extern const double myGravity;
} // namespace ExternalConstants

#endif
22 changes: 22 additions & 0 deletions src/core/linkage/sharing/inline/constants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// global constants as inline variables:

// If you need global constants and your compiler is C++17 capable, prefer defining inline constexpr global variables in a header file.
// Advantages:
// Can be used in constant expressions in any translation unit that includes them.
// Only one copy of each variable is required.
// Downsides:
// Only works in C++17 onward.
// Changing anything in the header file requires recompiling files including the header.

#ifndef ICONSTANTS_H
#define ICONSTANTS_H

// define your own namespace to hold constants
namespace InlineConstants {
inline constexpr double pi{3.14159}; // note: now inline constexpr
inline constexpr double avogadro{6.0221413e23};
inline constexpr double myGravity{
9.2}; // m/s^2 -- gravity is light on this planet
// ... other related constants
} // namespace InlineConstants
#endif
21 changes: 21 additions & 0 deletions src/core/linkage/sharing/internal/constants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

// global constants as internal variables:
// Advantages:
// Works prior to C++16.
// Can be used in constant expressions in any translation unit that includes them.
// Downsides:
// Changing anything in the header file requires recompiling files including the header.
// Each translation unit including the header gets its own copy of the variable.

#ifndef INCONSTANTS_H
#define INCONSTANTS_H

// Define your own namespace to hold constants
namespace InternalConstants {
// Global constants have internal linkage by default
constexpr double pi{3.14159};
constexpr double avogadro{6.0221413e23};
constexpr double myGravity{9.2}; // m/s^2 -- gravity is light on this planet
// ... other related constants
} // namespace InternalConstants
#endif