Is there a scope shared between instances of a template class? - c++

Besides the global scope, of course.
I have a custom assertion class with a macro to cache a reference to __FILE__:
#define DEFINE_THIS_FILE \
static const char THIS_FILE__[] = __FILE__
For source code, using the macro is no big deal since each source has its own scope. However, templated classes can't use source code, so I'm forced to do all my ASSERT() calls in the declaration/definition given by TemplateClass.h
If I use my macro outside of the class definition e.g. Singleton
DEFINE_THIS_FILE;
namespace NE
{
template<typename T>
class Singleton
{
...
}
}
Then the macro winds up in the same scope of any code that #includes Singleton, and the compiler throws a redefinition error for THIS_FILE__. (Of course, this only happens if the other code also uses the DEFINE_THIS_FILE macro.)
If I put the macro inside the declaration, the compiler won't complain but the linker won't be able to find THIS_FILE__ for any given instance of templated class e.g. Singleton:
namespace NE
{
template<typename T>
class Singleton
{
constexpr DEFINE_THIS_FILE; // constexpr modifier required in this case
...
}
}
I assume the linker error I get,
Undefined symbols for architecture x86_64:
"NE::Singleton<NE::NonTemplateType>::THIS_FILE__"
is caused by the template instances not existing in the same scope as where THIS_FILE__ was first defined, Singleton.h
OT: Is there a way to get all instances of my templated type Singleton to share a scope (global is unacceptable) so that all instances can use this static const macro?
Edit1
Further testing confirms: Using the macro DEFINE_THIS_FILE inside each templated method containing an ASSERT() will compile and run correctly....
In this case, the instances aren't sharing a scope, but have a static const char THIS_FILE__ defined for each method. This works, but I suspect that it uses as much or more ROM than a std::assert (with its its implied allocation of __FILE__).
I'll settle for this until an answer to OT comes about :)
Edit2
Silly me. Instead of using the workaround listed in edit above, I might as well create another macro, UNCACHED_ASSERT(argsToCheck) that directly uses __FILE__ instead of a const static representation.
Multiple ASSERTions per method could still benefit from the caching, though.
Still need an answer to OT, though.

You can place your declaration in unnamed namespace
#define DEFINE_THIS_FILE namespace { static const char THIS_FILE__[] = __FILE__; }

Related

Define a global variable template?

Usually, we do declare but not define a global variable in the header file. However, we define templates in it. Then the issue arises: is it possible to define a global variable template?
template <uint8_t PinCode>
uint8_t BitMask = digitalPinToBitMask(PinCode);
In reality, a global variable template:
instantizes only if at least one compile unit (CU) requires it.
causes no redefinition errors if multiple CUs require the same instance.
is shared among CUs, i.e., if one CU changes the value of an instance, other CUs requiring the same instance will be affected.
calls the initializer only once for each kind of required instance.
After longer research, I finally found the most elegant solution. The definition style depends on whether you want to initialize the variable.
If the variable does not need initialization, you only need a header file:
template <int TimerCode>
int TCCRB;
Yes, it is and must be so simple. Don't add "static" or "extern" keywords like we usually do for variables in a header file. It will pass compilation and work as a global variable template among all CUs. Same instances will share the same actual variable, i.e., changes in one CU will affect other CUs, as long as they have the same template arguments.
As we know, if you define a variable with no necessary keywords like "static" or "extern" in a header file, it will cause a redefinition error if the header is included in more than one CUs. "static" tell the compiler to copy this variable for each CU as individual variables, so changes in one CU won't affect that in another CU. Instead, "extern" tells the compiler that this variable here is only a declaration. It's defined and owned in only one of the CUs, and other CUs should only keep a reference or symbol to it. So that changes in one CU WILL affect other CUs.
However, a variable template is neither a static definition nor an extern declaration. It's a special instruction to the compiler: find all cases of references to this template, combine those of the same template arguments, and generate one definition automatically for each unique instance! This time the compiler takes the responsibility to avoid redefinition: it scans all CUs and then generates unique definitions itself!
This automatic definition is so convenient if you don't want to give the variable an initial value, and if there are too many possible instances to be listed one by one. However, if you do want an initial value, you'll have to define it yourself, and you'll need an individual CU to own these variables to avoid redefinition:
//In the header file:
template <int TimerCode>
extern int TCCRA;
//In the CPP file:
template <>
int TCCRA<1> = 2;
template <>
int TCCRA<2> = 5;
//Naturally you have to provide initial values for all possible instances …
For this case, the "extern" keyword is necessary because you explicitly defined all valid instances in your specially provided CU, and other CUs must refer to this definition. The compiler shouldn't generate a random definition itself. This is very much like a normal global variable definition, only adding some template grammars. However, the user can only use instances provided in your CPP file. This is also very natural because only for known instances can you provide an initial value.
I found very few tutorials on this topic on the Internet. I hope my experience will help more people ~
The standard defines many global constants which are templatized such as the type traits type_trait_v constants.
They are defined as such in the header
template<class T>
inline constexpr some_type some_variable = ...;
In your example you could do something like
template<uint8_t Pin>
inline constexpr uint8_t BitMask = digitalPinToMask(Pin);
For this to work then digitalPinToMask must be invocable in a constexpr context.
(Not to be confused with C++11 Extern Templates)
Ok, so after a long while battling compilers and linkers, the best solution I came up with for declaring a global variable that is a template with extern linkage is:
// lib.hpp
#pragma once
namespace lib {
template <typename T>
struct _GlobalTemplateExternImpl {
std::array<T, 2> value;
};
template <typename T>
inline auto &global_template_value = _GlobalTemplateExternImpl<T>::value;
}
// lib.cpp
#include "lib.hpp"
template
struct lib::_GlobalTemplateExternImpl<int>;
template <>
std::array<int, 2> lib::_GlobalTemplateExternImpl<int>::value = {}; // NOTE: the assignment (`= {}`) is important to do
template
struct lib::_GlobalTemplateExternImpl<float>;
template <>
std::array<float, 2> lib::_GlobalTemplateExternImpl<float>::value = { 7.0f, 66.6f };
// main.cpp
#include "lib.hpp"
#include <iostream>
int main() {
using namespace lib;
std::cout << global_template_value<int>[0] << "\n";
std::cout << global_template_value<int>[1] << "\n";
std::cout << global_template_value<float>[0] << "\n";
std::cout << global_template_value<float>[1] << "\n";
return 0;
}
And since C++ needs silly acronyms, I shall dub this the "Implicitly Externed Template Global Pattern" (IETGP) since the keyword extern is nowhere to be found.

C++ equivalent of #define for integers

I am looking for a portable one line replacement for the #define in the following code. The replacement should hide the word APPLE in the namespace of the Foo object.
class Foo {
public:
#define APPLE 123
Foo(int a) : a_(a) { }
};
// elsewhere in another file
Foo f(APPLE);
I tried to make this more C++ friendly this, and it worked using the Intel 2017 compiler:
class Foo {
public:
static constexpr int APPLE = 123;
Foo(int a) : a_(a) { }
};
// elsewhere
Foo a(Foo::APPLE);
but it does not work with g++ ((GCC) 6.3.1 20170216), because it gives the error
undefined reference to Foo::APPLE
because it is probably trying to take a reference to APPLE.
I know I can "fix" the problem by creating definition in a *.cpp file of
constexpr int Foo::APPLE;
but that violates my ideal of having the #define be replaced by 1 line. My Foo class is header-file only, and now I would need a cpp file just for the definition of Foo::APPLE. I know I could also declare APPLE as a function (static constexpr int APPLE() {return 123;}) but that is a whole lot more typing in the declaration and at every point of use I need to call the function with ().
It seems easier just to use the #define and be done with it. Non-static const int works fine, but APPLE is not usable as an argument to the constructor. Maybe there is a good reason why this is impossible in C++.
Edit: This is not a duplicate of Undefined reference to static constexpr char[]. That question is related to a string and why the particular error message comes up. I am trying to avoid using static linkage all together (I acknowledge in my question that I am aware of how to do static linkage) and I want to do it a "better/cleaner" way, and I see from the Answers that the way that passes my criteria is to use enum.
You've already listed most alternatives in your question. You'll need consider which approach you want to take:
Use inline variable which requires C++17 (your first attempt works implicitly in this standard)
Define the static member in a source file, which you don't want to do
Use an inline static member function instead, which you also don't want
Use a namespace scoped constexpr variable instead of a member
Use a member enum: enum : int { APPLE = 123 };
Use the macro (don't pick this)
In addition to the things mentioned already, there's also "poor man's inline variables":
static constexpr const int& APPLE = std::integral_constant<int, 123>::value;
You define a class template with a constant static data member whose value is what you want. You define that static data member out-of-line - but in the header, since it's a static data member of a class template. In this case, std::integral_constant does all that already, so you don't have to write your own.
Then, you define your actual static data member constant as a constexpr reference to that class template static data member; no out-of-line definition is needed because it is not possible to odr-use a reference initialized by a constant expression.

how to check if a macro is called within a class?

Say there is a macro:
#define X(...) foo(__VA_ARGS__)
foo is defined as:
void foo(int a) {}
template<class T>
void foo(int a, T& t) { std::cout<<a<<t.b; }
I'd like to check if X is called within a class or not. If it is called within a class, then I can call the second version foo(100,*this). Otherwise, I'll call the first version without passing *this.
It isn't possible, strictly speaking, to have a macro recognize whether it's invoked within some class or not. You see, macros are expanded by a preprocessor - not by the C++ compiler proper; and the preprocessor has no clue about C++ - it just works on text files. When the actual compiler gets to recognizing the class, the macros are all gone already.
However, you can use some more macros to sort-of achieve this:
#define IN_CLASS_FOO 1
class foo {
/* ... whatever ... */
}
#undef IN_CLASS_FOO
#define IN_CLASS_FOO 0
with this in place, you can modify your X macro to use IN_CLASS_FOO for controlling its behavior. Note that if you expand some code which refers to a this variable, it will have to be defined even if you're not within a class, so it would still not be possible to just use it.
I strongly discourage you from doing so, however - you would most likely be better served by avoiding macro use altogether. Try replacing the macro with a constexpr function.
The keyword this is available within the body of any non-static member function.
Once I saw a pretty old code in macroses like this:
__if_exists(this) \
{ \
// Do something
} \
Statement __if_exists checks in compile-time if the identifier is available in this scope.
But be careful, it is supported by MSVS only, and in general, it is not good to use such things in the code.
Too little information in the question, so the following could be a match or it might not...
class C
{
void foo(int a)
{
::foo(a, *this);
// ^^ resolves to global scope
bar::foo(a, *this);
// ^^ assuming foo resides in namespace "bar"
}
};
So you now have a member function that will be selected whenever you call e. g. foo(77) within the class context, otherwise, the free foo overload will be selected. The macro gets pointless, just drop it.
If it is OK for you that the template parameter will be resolved to class C only, even if called from within sub classes, you could inherit from C for not having to repeat this code in every sub class. Otherwise, you'll get away with curiously recurring templates...

How to make a debuggable file scoped (static?) class in c++?

I define a lot of classes in my cpp files. Often with unimaginative names, such as 'Implementation'. and am worried about name collisions, as these are horrible to debug (assuming the compiler silently drops one of the definitions). However, I also want to be able to debug my program, so anonymous namespaces are not an option. So, can file-scoped (aka. translation-unit scoped) classes be defined in c++ without using namespaces? If yes, how?
File-scoping in c
In c, one can create a global variable with int foo;, and limit the variable to file-scope using static int foo;. Similarly, file-scoped functions are also created with the static keyword, for example static void bar();. And structs do not define data or executable code, and thus are effectively always file-scoped.
Virtual member functions
Now c++ introduced virtual member functions, which caused structs (aka. classes) to contain data and executable code. Hence structs are now globally defined. However, it is not allowed to use static to make the struct file-scoped again. I.e. static struct Foo{}; does not compile.
Namespaces
To tackle the problem of name collisions, c++ also introduced named namespaces. Those can also be used to wrap the struct, such that it becomes pseudo-file-scoped. Though this still forces you to pick a unique name (that you don't even care about) for every file. As a solution, they also introduced anonymous namespaces. Unfortunately, neither gdb nor the visual studio debugger seem to support anonymous namespaces (it is basically impossible to refer to anything inside the anonymous namespace).
A partial solution is to use anonymous structs/classes and typedef these, as both are file-scoped (C - Limit struct Scope), except that it is impossible to explicitly define constructors or destructors (Constructor for a no-named struct). The following example compiles and runs fine with gcc and also allows gdb to put a breakpoint on method():
interface.h:
struct Iface {
virtual void method()=0;
};
implementation_a.cpp and implementation_b.cpp:
#include "interface.h"
typedef struct : Interface {
virtual void method();
} Implementation;
void Implementation::method() {
// Do stuff...
}
Interface * new_implementation_a() { // or new_implementation_b
return new Implementation();
}
main.cpp:
#include "iface.h"
int main() {
Interface * a = new_implementation_a();
Interface * b = new_implementation_b();
a->method();
b->method();
return 0;
}

C++ nested macros?

Is there any way, in C++, to define nested macros/constants within a class, in a similiar fashion to nested typedefs, or a method to acheive similiar functionality? The motive is generally for the macros to be used by templates.
class SomeClass
{
public:
#define SomeConstant 123
};
int x=SomeClass::SomeConstant;
Ofcourse, static const members can do the job, but those are physical variables, while I'm looking for a simple macro-like behavior.
You can't do what you want with macros. Macros have no concept of scoping.
But for simple int values you can do what you want with enums.
class SomeClass
{
public:
enum {
SomeConstant=123
};
};
int x=SomeClass::SomeConstant;
A fully scoped name for the value, but no space taken for it, even in debug builds - you couldn't take its address if you wanted to.
Const values declared and defined in-place are exactly what you need here: the compiler can and will optimise them away completely so they end up being exactly the same as using the #define in the first place, but with the benefits of strict scoping.
class SomeClass {
public:
static const int someValue = 10;
};
This doesn't take up any extra space - no memory is allocated to store "someValue". You can prove this: if you try and use the "someValue" as a real object (ie you try and get its address), then the linker will tell you it's undefined.
Macros completely ignore scope - they are expanded before the C++ compilation. You just can't do that.
Use of static const often leads to no variable being allocated - the compiler treats it as a constant.
Macro pre-processors generally don't have any idea of language context; thus they don't know what a "class" is making "nesting inside a class" not make sense in the first place.
For what you want, either use static const, or use the full name (assuming the preprocessor allows colons in macro names, not 100% sure on that) - though it won't allow you to inherit the constant on derived classes:
#define SomeClass::SomeConstant 123
You can do this with templates:
template < int someConstant = 123 > class SomeClass
{
public:
void outputConstant() { cout << "We think the answer is:" << someConstant; }
}
But that isn't precisely what you want because you have to declare an instance of the class as:
int main(int argc, char *argv)
{
SomeClass<123> myInstance;
}
I know others have explained the bit about macros, but allow me to add: #define is processed by the pre-processor, not the compiler. In the standard is a section called "translation phases" which explains this in more detail, but for your question the point is that macros are evaluated before the class is even compiled, and the scope at which the #define occurs is not known.
The authoritative book on this subject (programming with templates during the compile stage) is Modern C++ Design: Generic Programming and Design Patterns Applied, by Andrei Alexandrescu.
I don't understand your objection to using a static const.
It will not effect the size of your class, and the compiler will optimise to achieve what you think you'd get from a macro.
"Static members are physical variables".
What's against this? The only reason to object to this would be memory usage. But since the member is static, the memory would only be occupied once with the intended content.
On the contrary, with a macro, the contend would be present at every single usage location in the binary.
EDIT:
In case the variable is of an integral type, smaller than a pointer, it's probably best to define the constant in the class declaration. Optimizing compilers can then inline the value in the calling code, just like for a macro.