Linking Static Variable in Abstract Class [duplicate] - c++

Say that I have a class that requires a few constants to function. Several member functions require use of these constants. Use of #define is frowned upon since it can cause collisions. The constants are hex patterns of 8 or 16 bits and are stored as uint8_t or uint16_t. These constants also don't change from instance to instance of the class, and therefore memory (albeit very little memory) can be saved by having only one copy of the constants.
Is there anything improper, or perhaps of better way of accomplishing the above instead of simply doing something like the following:
// mycode.h
// .......
class myclass {
private:
static const uint16_t kMyClassConstant_ = 0xBEEF;
// .......
};
Thanks in advance for the help.

Given your description of the situation, I'd say using static const members is a good approach. In C++11 you may want to change it into static constexpr to emphasize it's a compile-time constant, although nothing will effectively change as a result of that.
If you refer to myclass::kMyClassContant_ somewhere in the code in a way that is relevant under the one-definition-rule (odr), esp. in contexts that require a reference (including const-reference), the compiler will complain that there is no definition of the constant. Merely declaring and initializing it inside the class isn't sufficient in this case. This may force you to separate declaration and definition:
// mycode.h
class myclass {
private:
static const uint16_t kMyClassConstant_;
};
// mycode.cpp
const uint16_t myclass::kMyClassConstant_ = 0xBEEF;
To avoid the trouble of maintaining separate declarations and definitions, some people prefer declaring an inline constexpr function instead of an actual variable:
// mycode.h
class myclass {
private:
static constexpr uint16_t kMyClassConstant_()
{ return 0xBEEF; }
};
This is a correct work-around for many of the odr-related problems, and it does not cause any loss in performance. Whether it is really useful depends on how much of a burden it is to maintain separate declarations and definitions of an ordinary static constant. If you expect your constants to never change as your code evolves, using ordinary static constants with separate definitions is preferable. But if you modify the definitions of the constants frequently, having to re-compile the definition file and re-link it to all relevant parts of the project may make you consider the function-based solution above as a better alternative.
A final comment on the data type: Forcing it into 16 bits using std::uint16_t can be useful if you need to store lots of these values in compact form. Otherwise, the actual size may not really matter, in which case std::uint_fast16_t (which may be larger than 16 bits) may be better.

You could use type traits to implement this:
#include <type_traits>
class myclass {
private:
typedef std::integral_constant<uint16_t , 0xBEEF> kMyClassConstant;
// ...
};
used as myclass::kMyClassConstant::value.
This shows the purpose of implementing an integral constant and prevents you from accidentaly taking an address of the constant.

Since C++17, we have access to inline variables, which take care of the odr-related problems. Several options:
// mycode.h
class myclass {
static const inline uint16_t kMyClassConstant_ = 0xBEEF;
};
Or, if it can be marked constexpr (like in this case):
// mycode.h
class myclass {
static constexpr inline uint16_t kMyClassConstant_ = 0xBEEF;
};
Which can be simplified to:
// mycode.h
class myclass {
static constexpr uint16_t kMyClassConstant_ = 0xBEEF;
};
Because in C++17 constexpr implies inline for static data members.

Related

constexpr in class without static

I have a situation where I need to store a compile time constant in a header, and I do it in the class I'm using it in as I don't want to expose the constant to other files that include this header. (as well as the fact that it depends on another hidden struct)
Like this:
namespace ns {
class bla {
private:
struct internalStruct {
// ...
};
// I put it in the class as I don't want other files to be able to see this
constexpr const size_t compileConstant = sizeof(internalStruct) * 8;
};
}
The problem is I get a
Constexpr is not valid here
error. The solution is to add static, however I read that constexpr integral members should be inline.
What should I do?
Adding static should be perfectly fine for your use case. That's what the reference states too:
A constexpr specifier used in a function or static data member (since
C++17) declaration implies inline.
And since this is a compile-time constant, you might as well have it shared across all class instances rather than on a per-instance basis (which is usually how even const variables are used).

Static constexpr data member initialized off-class, and a possible workaround?

From elsewhere I know that it's not possible in C++17 to declare a static constexpr data member without its immediate initialization (although yet elsewhere they use such example).
// --- in header ---
struct Data{
LPCTSTR str;
int i;
};
class C{
public:
static constexpr Data MyData; // VS complains: this requires an in-class initializer
};
// --- in implementation file ---
constexpr Data C::MyData={
_T("Hi"), 12345
};
My code must, for the time being, compile also in older Visual Studios where the lack of constexpr concept can easily be #defined as
#if _MSC_VER<=1600 // pre-C++11 compiler?
#define constexpr const
#endif
and suddenly the code base would be compatible with virtually anything from VS6 to VS2019. Correct me if the off-class initialization is allowed by means of some hidden command-line switch in Visual Studio.
So I came up with a workaround about whose validity I'm not sure. Unlike data members, static constexpr methods don't have to have an in-class body. So I do:
// --- in header ---
struct Data{
LPCTSTR str;
int i;
};
class C{
public:
static constexpr Data GetMyData();
};
// --- in implementation file ---
constexpr Data C::GetMyData(){
constexpr Data D={
_T("Hi"), 12345
};
return D;
}
I can then benefit from constexpr, yet still compile (with the help of the above #define) under older Visual Studios:
constexpr LPCTSTR Greeting=C::GetMyData().str;
and also surprisingly take the address of the returned object at run-time:
const Data *p=&C::GetMyData();
const LPCTSTR greeting=p->str;
which is great and desired in my app! But makes me worry about the address of what I have received? Is it the address of the object compiled into the resulting executable (and at run-time residing in the protected memory) or an address of a global variable created really at run-time? I of course want the earlier to occur when compiling under newer Visual Studios, whereas I don't care about the situation under pre-C++11 versions.
Thanks in advance.
The key point is that constexpr does not mean "exists only at compile time", but instead "can also be used at compile time. So as long as you don't access the constexpr variable in a way that requires the value to be accessible at compile-time, it can be treated as if it was a const.
In fact, with the code you posted, the only place where you ever see the benefits of constexpr is inside of the implementation file. Anywhere else, it has not choice but to be "degrated" to a regular const since resolving its value during compilation is impossible.
I think most of your questions can be cleared up by deconstructing the code a bit into an equivalent example:
// MyClass.h
class MyClass {
// static constexpr Data MyData;
static const Data MyData;
};
// MyClass.cpp
namespace {
constexpr Data MyDataValue = ...;
}
const Data MyData::MyData = MyDataValue;
// If you use MyData inside of the implementation file, it gets the conxtepr value.
void MyClass:foo() {
// std::array<float, MyClass::Data.some_member> some_array;
std::array<float, MyDataValue.some_member> some_array; // no problem
}
// Some_other_file.cpp
int foo() {
// That's fine, MyClass::Data will be resolved either at runtime or during lto.
return MyClass::Data.some_member;
}
int bar() {
std::array<float, MyClass::Data.some_member> some_array; // ERROR! Can't be resolved at compile time
}
So what's the point of being able to declare a static constexpr data member without its immediate initialization?
As long as you define it later inside a header before it's actually used, then everything is fine, which can sometimes come in handy. However, in your case, since you want to define the variable inside an implementation file, you create this two-tiered system where the member is constexpr in the implementation file, and const anywhere else.
All this to say: If all your delayed constexpr definitions are in implementation files like in your posted code, then just make them const, and use locally a constexpr in an anonymous namespace inside of the implementation file if you need it there. No need for the macro at all.

Where to define compile-time constants?

I made a super simple design to start solving a problem.
Now, this might seem like super trivial at first, but since there are tons of ways to do this, it confuses me, due to my lack of professional experience.
Where would I define those compile time constants? (Always suppose I'm using the highest current C++ standard version)
In a namespace? Inside the class? In a .h outside the class? In the .cpp outside the class? Just use them as magic numbers and add some comment? static? non-static? const? constexpr? template the deck size in case its bigger?
What I thought of:
class JolloManager
{
private:
constexpr static int rounds = 3;
constexpr static int deckSize = 52;
constexpr static int princeId = 1;
constexpr static int princessId = 2;
std::array<int, deckSize> deck;
public:
JolloManager() {};
};
Is this correct?
In C++17, defining compile-time integer constants is easy.
First, you should decide whether or not the constant should be scoped to a class. If it makes sense to have it as a class member (e.g., it pertains to the concept that the class represents) then make it a class member. Otherwise, don't.
As a class member, write:
class JolloManager {
constexpr static int rounds = 3;
};
That's it. No out-of-line definition is required anymore in C++17.
If it's not going to be a class member, but you want everyone who includes your header to be able to access the value, then write this in the header:
inline constexpr int rounds = 3;
(Technically, the reason to use inline is to avoid ODR violations when the variable is ODR-used by an inline function in multiple translation units.)
If the value is an implementation detail that only one .cpp file needs access to, then write the following in that .cpp file to give it internal linkage (i.e., prevent clashing with names in other translation units):
constexpr int rounds = 3; // no `inline` this time
Finally, if the constant is only needed by a single function, you can make it local to that function:
void foo() {
constexpr int rounds = 3;
}

c++11 class member array size constexpr forward declaration

I want to exclude some headers from my include chain after having used them. From what I know there is no exclude "header.h" in c++11.
Pseudo Code Wishful thinking:
#include "the_bad_header.h" //long includechain with later unused declarations
class bulky { ... };
constexpr std::size_t bulkysize = sizeof(bulky);
forget everything included and class bulky and remember only bulkysize
My example where the problem becomes evident follows. Please don't argue this is not a serious problem. The Example is broken down to show the minimal abstract language usage. I will describe the old fashioned solutions and their disadvantages too.
Old style solution
justanotherheader.h:
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
};
justanothercppunit.cpp:
#include "justanotherheader.h"
#include "boost/lotsofheaders.hpp"
//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
bulkywrap::bulkywrap()
: pImpl( new bulkywrap_pImpl() )
{}
My current Solution
justanotherheader.h:
#include "stdint.h" // this is the only header I like to use, but also unnecessary.
#define UNKNOWNSIZE 12345
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
uint8_t pImpl_Placement[UNKNOWNSIZE]; //placement new for pImpl
};
justanothercppunit.cpp:
#include "justanotherheader.h"
#include "boost/lotsofheaders.hpp"
//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
bulkywrap::bulkywrap()
: pImpl( new(this->pImpl_Placement) bulkywrap_pImpl() ) //using this here is safe
{}
So, the code above is working. The advantages are: hiding complexity and having no runtime dynamic memory indirections. Huh? I mean, the placement new allows the whole object to be put on stack and all member addresses are known at compile time. My attempt is to have best performance while using interface design of opaque pointer.
If you think: "this performance advantage is not worth the thinking effort." then please leave that question.
My expected Solution
justanotherheader.h:
#include "stdint.h" // this is the only header I like to use, but also unnecessary.
constexpr std::size_t get_bulkywrap_pImpl_Size( void ); //constexpr function forward declaration
extern constexpr std::size_t bulkywrap_pImpl_Size; //constexpr literal forward declaration with external initialization
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
uint8_t pImpl_Placement[get_bulkywrap_pImpl_Size()]; //undefined constexpr used
uint8_t pImpl_Placement[bulkywrap_pImpl_Size]; //alternative to above. undefined constexpr used
};
justanothercppunit.cpp:
#include "justanotherheader.h"
#include "boost/lotsofheaders.hpp"
//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
constexpr std::size_t get_bulkywrap_pImpl_Size( void )
{
return sizeof(bulkywrap_pImpl);
}
constexpr std::size_t bulkywrap_pImpl_Size = sizeof(bulkywrap_pImpl);
bulkywrap::bulkywrap()
: pImpl( new(this->pImpl_Placement) bulkywrap_pImpl() ) //using this here is safe
{}
In my current solution I need to verify the sizeof(bulkywrap_pImpl) and adjusting UNKNOWNSIZE manually.
I think it is currently not possible to get any information from a compilationunit to others. I know this is typically intended by good reason, but this limits the possibilities of c++11.
I want to point out:
jtc1 sc22 wg21 paper n3337
jtc1 sc22 wg21 paper n3308
Please help me to find information weather and why the standard does not allow this.
But furthermore I would like to find a solution of how to export some literal constant during compiliation time out of a compileunit into another compileunit. It's just a literal, so all statements and expressions are not affected by it. Thus compilation does not depend where the size of the array comes from.
My suggestion results in some work for the ISO-jtc1-sc22-wg21 and the compiler developers, but I don't see any relevant difference between template and constexpr since every definition must appear in the same translationunit. This makes modular programming and clean interfaces bogus.
And no: I don't want to use preprocessor macros, dynamic new or virtual member functions. Of importance is maximal const-correctness, since the size of the class is const.
Please help
you can't have both "compile-time" and "from another compilation unit" at the same time. also it's not clear why do you need to forget successfully parsed header. parsing time already consumed. i suggest you to create another header with size constant, include it from both files, and add static_assert to pimpl file, checking that constant >= sizeof(pimpl). you can generate this header as part of your build system by compiling source file including pimpl and doing cout <<sizeof(pimpl). also i suggest you to not waste time and space for pimpl pointer and replace it with member function, returning address of properly cast buffer. also you failed to show where you call pimpl's destructor. also implementing assignment/copy/move/swap will be a lot of fun
use static_assert in cpp to check that size declared in header >= size of impl class

Why can't we have non-const class-level static variables?

Why does the Visual C++ compiler refuse to compile this code?
I obviously know that the error is:
Error C2864: Singleton<T>::p:
Only static const integral data members can be initialized within a class
but why? (i.e. is there a technical reason why it is not allowed?)
Is this compiler-specific behavior or is it mandated by the standard?
It seems to be fine at the global scope, so why not at the class scope?
It also seems like not all compilers mind this.
Also, what is the proper way of fixing this?
template<typename T>
struct Singleton
{
static T *p = 0; // Error C2864
static T *getInstance() { /*...*/ return p; }
};
That's standard behavior. Only static const integral members can be initialized without a proper definition. All other types need to be defined somewhere, and the initialization is written at the point of definition:
template<typename T>
struct Singleton {
static T *p;
static T *getInstance() { /*...*/ return p; }
};
template<typename T>
T *Singleton<T>::p = 0;
Objects must be defined somewhere. If you define them within your class then its defined at a header file, and you get a different object for each compilation unit that includes it. This is relaxed for const integral types and if you don't define them then the compiler just replaces it with its literal value. Taking the address of such static const integral would still result in a linker error if no definition is provided.
You can have this type of variable, but you cannot initialize it inside the class definition. The only type of variable that may be initialized the way you are asking is a static const.
A fixed version of your class definition removes the = 0, and adds this below the class definition:
template<typename T>
T *Singleton<T>::p = 0;
This is standard behavior. I'm not sure there is a technical reason, my guess would be it is for consistency with instance members (which cannot be initialized this way, either). Instance variables, of course, have constructor initializer lists instead.
As everyone pointed out, you cannot define a non-const, non-integral type in the body of a class (at least not with C++03, it changed with C++11 but I'm not sure how exactly). However, you can do it differently and clean.
template<typename T>
struct Singleton {
static T* getInstance() {
static T* p = NULL;
/*...*/
return p;
}
};
Declarations are meant to go into header files, where they will be compiled many times - each place they are included.
Static variables should only have one definition, so that only one copy will exist in the entire program. This means it needs to be in a source (.cpp) file. Assigning the value needs to be put at that spot.
Static constant integers are an exception to the above rules, because they can become compile time constants. When they're used, a literal value is substituted for the class member.
You cannot assign a non-static in the class body like that. Instead, assign the value outside the class (usually in your cpp file)
template<typename T>
struct Singleton {
static T *p;
static T *getInstance() { /*...*/ return p; }
};
template<typename T>
T *Singleton<T>::p = 0;
The interesting question is not the one you ask, but rather the opposite:
Why are const integral static members allowed to be assigned a value in the declaration?
The important bit of the question is declaration. The value that a variable gets is set in the variable definition, and that is consistent with non-const or non-integral static members of a class, where in the class you only offer a declaration. The initializer value is provided in the definition that is outside of the class definition, commonly in a .cpp that guarantees that it will be defined in a single translation unit.
But why can integral static constants have a value in the declaration?
For practical reasons. The compiler can use integral constants as compile-time constants, that is, it can actually replace the value of the constant in place of the identifier in all places where the constant is used as an rvalue, for example when defining the size of an array. But if the value is only present in the definition in a single translation unit, the compiler cannot possibly use it in all other translation units. As an example:
// fq.h
struct fixed_queue {
static const std::size_t max_elements; // [1]
int data[ max_elements ]; // Error: How big is data??
};
// fq.cpp
#include "fq.h"
const std::size_t fixed_queue::max_elements = 10;
If max_elements was not allowed to have a value in the declaration [1], then you would not be able to use that constant to define the size of the array data, which is a quite sensible use for a static constant.
Why not extend this to all other cases?
Because it does not seem to make much sense... Providing the value in the class definition cannot be used by the compiler in any other circumstance, and thus it is not needed, so only integral constants need to be treated differently.
The reason is that non-integral, non-const values require a memory location.
const int can be handled statically by the compiler and built directly into certain machine instructions, floats and more exotic objects need somewhere to live because the machine instructions will only operate in terms of their address.
In principle, the language could have allowed this, but it would mean either generating extra objects and bloating the binary (ok for consts), or making life hard for the compiler writers for non-consts: redundant copies would have to be dropped to preserve the one-definition rule (this is what template instantinations have to do, by the way).