Static const integer class member in header-only file - the proper way? - c++

Say I have the following example:
#include <cstdlib>
class A {
public:
static const std::size_t value = 42;
};
In short, I have (or better, want) a class A with a static const std::size_t member called value with the value 42 (determined at compile time).
Now, IIRC, this only works fine under certain circumstances. It doesn't, for example, when you take the address of A::value. In order for this to work fine in all cases you'd need to add a definition in some implementation file:
const std::size_t A::value;
However, I can't do this, because I want this file to be header-only. Another common solution is this:
class A {
public:
enum { value = 42 };
};
I don't like this solution either, because I'd like the type of A::value to be std::size_t.
What is a good solution to this problem? Preferably a small and portable solution, not something with huge macro magic like BOOST_STATIC_CONSTANT.
I'd like a solution for C++03, not C++11 (it's trivial there).

First of all, using the unsigned size_t type for numbers, you're likely to run into implicit promotion problems. So, good idea to use its corresponding signed type, which is called ptrdiff_t. Which, as it happens, is the result type of a pointer difference expression.
Also, due to changes in C++11, it’s generally a good idea to include <stddef.h> and not <cstddef>, i.e., write ::ptrdiff_t or just plain ptrdiff_t, not std::ptrdiff_t.
Now, here's how to do the header file extern linkage constant thing:
template< class Dummy >
struct A_constants_
{
static ::ptrdiff_t const value;
};
template< class Dummy >
::ptrdiff_t const A_constants_<Dummy>::value = 42;
typedef A_constants_<void> A_constants;
class A
: public A_constants
{
public:
// Whatever
};
Then you can use it like this:
foo( A::value );
There are also some other ways of doing this, but the above is about the simplest and easiest to get right.

Related

Static variable with templates

I want to store some additional information about classname during inheritance:
#define CLASS_TO_STRING(name) #name
class IBase {};
template <typename T>
struct BaseManager
{
static const char* MANAGER_TAG = CLASS_TO_STRING(T);
};
std::map<const char*, IBase*> mManagers;
template <typename T>
void addManager(BaseManager<T>* manager)
{
mManagers[T::MANAGER_TAG] = manager;
}
So, when I call addManager with some object of type inherited from BaseManager I get an error that BaseManager<TYPENAME>::MANAGER_TAG is undefined. I understand the reason of the problem but can't understand how to resolve it.
Apart from marcin_j's comment about in-class initialization (which works only in C++11 and for nonintegral types it requires constexpr), the real problem is this:
static const char* MANAGER_TAG = CLASS_TO_STRING(T);
When this line gets parsed by the preprocessor, CLASS_TO_STRING will turn T into the string literal "T". What's really going on here is that the preprocessor (the one performing macro substitution) has absolutely no idea of the template system and that T is a template parameter. You need a different approach here.
You can change const char* to constexpr but I am afraid all you will get from CLASS_TO_STRING(T) is T (at least g++ gives me T on output - and thats because preprocessor runs before compilation and template instantiation).
also instead of T::MANAGER_TAG, you should BaseManager<T>::MANAGER_TAG. And your BaseManager should inherit from IBase if :
mManagers[BaseManager<T>::MANAGER_TAG] = manager;
is supposed to work.
The reason you get your error is I suppose that in-class initialization of static data member, works only for const integral types.

Define a static const Universal Unique Identifier (UUID)

Context
I oftenly use UUID implementation of Boost library to identify derived classes.
To do so I usually use the following :
In the declaration file :
#include "ClassA.h"
#include <boost/uuid/uuid.hpp>
class SubClass1 : public ClassA {
public:
static const boost::uuids::uuid classId; // 7feb24af-fc38-44de-bc38-04defc3804de
...
};
In the implementation file :
#include "SubClass1.h"
#include <boost/uuids/uuid_generator.h>
const boost::uuids::uuid SubClass1 ::classId = boost::uuids::string_generator()("{7feb24af-fc38-44de-bc38-04defc3804de}");
...
Question
I would like to know if it is possible to assign a value to the UUID in the declaration file.
Ideas
At first, I thought it was possible because Boost implementation is POD. Therefore I tried several ways to assign a value directly in the header using aggregate initializers (see boost documentation for an example of non static aggregate initializers) :
static const boost::uuids::uuid classId = { 0x7f, 0xeb, ... };
Unfortunately, it failed at compilation (the compiler can only initialize static const integral type).
Have you any suggestions to solve this issue, preferably using the Boost implementation of UUIDs ?
The easiest way to define a non-integral constant as a class member in a header file is to wrap it in a function, like this:
typedef whatever Uuid;
class MyClass
{
public:
static Uuid const& uuid()
{
Uuid const theValue = ...;
return theValue;
}
};
If you want it as an actual constant, not a function, then you can use a little templating trick, like so:
template< class Dummy >
class MyClass_constants
{
public:
static Uuid const uuid;
};
template< class Dummy >
Uuid const MyClass_constants<Dummy>::uuid = ...;
class MyClass
: public MyClass_constants<void>
{};
With C++11 you can use constexpr, like this:
class MyClass
{
public:
static Uuid constexpr uuid = ...;
};
but, although a test of that compiles fine with no linker warnings with g++ 4.7.1, it's so new that I'm not sure if the standard's One Definition Rule actually supports it, or whether, with such definition in multiple translation units, I'm into Undefined Behavior.
So, if you want to do the constexpr, perhaps ask a separate question about the ODR.
As an alternative you can wait for the C++2040 standard and then just write
inline static Uuid const uuid = ...;
It is food for thought that, as shown, this hypothetical future feature can be emulated even in C++98, i.e. that all that's needed is already implemented by compiler and linker, and has been since the first standard. And yet, that that simple feature is lacking in the language. I believe that it's due to a kind of haphazard historical language evolution.
Anyway, I'd go for the simple function wrapper shown first. :-)

Is it better to replace constants by template parameters?

Is it better to do:
const int MY_CONST = 20; // global constant in the program
class A {
// uses MY_CONST all over the class implementation and definition
}
or this?
const int MY_CONST = 20; // global constant in the program
template<int my_const>
class A {
//uses my_const only and never MY_CONST
};
//A<MY_CONST> used later in the program
Is one of these pattern better than the other? why?
thanks
Unless that global constant is used elsewhere outside of the class I would use neither of those approaches and make the constant a member of A:
class A {
public:
static const int MY_CONST = 20;
};
const int A::MY_CONST; // Possibly need definition also
And then use A::MY_CONST in your code.
The only time I would use a template is when you need to change the value depending on the instance for some reason.
template <int I>
class A
{
public:
static const int MY_CONST = I;
};
template <int I>
const int A<I>::MY_CONST; // Definition
Then create instances like so:
A<1> a1;
A<2> a2;
The second solution is sensible if it makes sense to instantiate e.g. A<MY_CONST + 1>, or A<0>, or any other value than MY_CONST. If, however, A is strictly designed to be used with the one value, then you don't gain anything from that. In that respect the first solution gives you everything you need.
One way to look at it is that you're introducing a dependency to A (only on a number, not on anything with behavior, but still that's a kind of dependency), and the question is whether to inject that dependency via a template parameter, or have the class pull in the dependency via a named const object.
I can see the template being useful for testing the class A -- you want to write the class to work with any value, so that you can change the value in future with confidence that you won't immediately get test failures and have to fix the bugs.
So, you could write the template and test it with lots of different values, even though no "real" program will use more than one instantiation of the template.
Obviously there are other ways to write a class whose behavior depends on an integer value, and test it. For example you could use a macro and have the test harness compile the code multiple times, or you could make MY_CONST an extern value and link the code against different object files containing different values, or you could make A store the value as a data member (even a static data member).
Which ones work for you depends how the class is going to use the value, but since a template parameter is an integer constant expression it's good for most uses that the const int is good for. You can't take a template parameter's address, is the only thing that immediately springs to mind.
I would always remove the global variable. Let's distinguish 2 cases, MY_CONST is either
an implementation detail in which case I would prefer to make it a private constant
class A
{
private:
static int const MY_CONST = 20;
};
or part of the class interface in which case I would prefer to make it a template parameter and provide it as a public member
template<int N>
class A
{
public:
static int const MY_CONST = N;
};
This way, users can not only read but also "write" (at compile-time) to MY_CONST. If users will not want to specify anything but a default value for N, you could provide a default template argument, or give a simple typedef
typedef A<20> DefaultA;

Multiple Integer-type classes in C++

I often find myself using Integers to represent values in different "spaces". For example...
int arrayIndex;
int usersAge;
int daysToChristmas;
Ideally, I'd like to have separate classes for each of these types "Index","Years" and "Days", which should prevent me accidentally mixing them up. Typedefs are a help from a documnentation perspective, but aren't type-safe enough.
I've tried wrapper classes, but end up with too much boilerplate for my liking. Is there a straightforward template-based solution, or maybe something ready-to-go in Boost?
EDIT: Several people have talked about bounds-checking in their answers. That maybe a handy side-effect, but is NOT a key requirement. In particular, I don't just want to prevent out-of-bound assignments, but assignments between "inappropriate" types.
Boost does in fact have a library specifically for this type of thing! Check out the Boost.Units library.
One funky "hack" you could use is a template non-type parameter to create wrapper types. This doesn't add any bounds but it does allow to treat them as different types with only one set of boilerplate template code. I.e.
template<unsigned i>
class t_integer_wrapper
{
private:
int m_value;
public:
// Constructors, accessors, operators, etc.
};
typedef t_integer_wrapper<1> ArrayIndex;
typedef t_integer_wrapper<2> UsersAge;
Extend the template with lower and upper bounds or other validation as you like. Not pretty by a long shot though.
You could try BOOST_STRONG_TYPEDEF. From boost/strong_typedef.hpp:
// macro used to implement a strong typedef. strong typedef
// guarentees that two types are distinguised even though the
// share the same underlying implementation. typedef does not create
// a new type. BOOST_STRONG_TYPEDEF(T, D) creates a new type named D
// that operates as a type T.
I remember solving a similar problem with a simple template where you would specify the allowed range, i.e.
Int<0, 365> daysToChristmas;
Int<0, 150> usersAge;
Int<0, 6> dayOfWeek;
You get the point. Now you could just derive from such a template type, like
class DayOfYear: public Int<0, 365> {}
and you could no longer pass a user age to a function expecting a DayOfYear, and you wouldn't have to use the angled brackets.
This is a generic "StrongType" template that we use to wrap different types and contexts. The only significant difference to this answer is that we prefer to use a tag-type that gives a meaningful name to each specialized wrapper type:
template <typename ValueType, class Tag> class StrongType {
public:
inline StrongType() : m_value(){}
inline explicit StrongType(ValueType const &val) : m_value(val) {}
inline operator ValueType () const {return m_value; }
inline StrongType & operator=(StrongType const &newVal) {
m_value = newVal.m_value;
return *this;
}
private:
//
// data
ValueType m_value;
};
And a use of the template as follows:
class ArrayIndexTag;
typedef StringType<int, ArrayIndexTag> StrongArrayIndex;
StringArrayIndex arrayIndex;
Notice too, that all of the functions are 'inline', the intention being that the compiler can do its best to generate exactly the same code it would generated had the template not been used at all!
In addition to the Boost Units library mentioned by Ryan Fox, there will be also the Boost Constrained Value library, which is currently under review.
Who knows when or if it will hit an official Boost release, but you can probably try it out anyway.
Adding in the operator int () will allow you to use the object where a normal int is required. You can also add in a operator = () to set it within range.
class DayType
{
public:
static int const low = 1;
static int const high = 365;
};
template<class TYPE>
class Int
{
private:
int m_value;
public:
operator int () { return m_value; }
operator = ( int i ) { /* check and set*/ }
};
Int<DayType> day;
int d = day;
day = 23;
I hope this helps.
int arrayIndex;
This is what std::size_t is for.
int usersAge;
People can't have negative ages and it is not useful/easy to set a fixed upper bound for ages. So here you should just use unsigned int.
int daysToChristmas;
Days to Christmas requires special attention. The number of days until Christamas can range from 0-366. The simple solution is to write the following wherever needed:
assert( 0 < daysToChristmas && daysToChristmas < 366 )
If you feel you're going to duplicate that assert in too many places, then David Allan Finch proposes a neat solution for this case. Though I am partial to using the assert.
For an array index I'd use size_t provided I didn't need negative values, because that's what it's there for. Of course that frequently is unsigned int, so won't give you any type safety at all. However, anything that did give you type safety (i.e. that stopped you assigning an unsigned int to an array index) would also stop you returning a size_t value into your type. That might be too much type safety anyway.
You could probably use an enum for bounded ranges:
enum YearDay {
FirstJan = 0,
LastDecInLeapYear = 365
};
You can assign YearDay to int, but you can't assign an int (or another enum type) to YearDay without an explicit cast. Any value between the least and greatest named value in an enum is a valid value for the enum. Assigning a value outside the range [0,365] results in undefined behaviour. Or possibly an unspecified or implementation-defined result, I can't remember.
Age is tricky, because it's almost bounded, but not quite. You could use 969 (age of Methuselah) in an enum, or a class wrapping an int with explicit conversions as described by others.
Check out this old CUJ article on this subject. IIRC the technique desribes how to make it work with all the fundamental operators

static const Member Value vs. Member enum : Which Method is Better & Why?

If you want to associate some constant value with a class, here are two ways to accomplish the same goal:
class Foo
{
public:
static const size_t Life = 42;
};
class Bar
{
public:
enum {Life = 42};
};
Syntactically and semantically they appear to be identical from the client's point of view:
size_t fooLife = Foo::Life;
size_t barLife = Bar::Life;
Is there any reason other than just pure style concerns why one would be preferable to another?
The enum hack used to be necessary because many compilers didn't support in-place initialization of the value. Since this is no longer an issue, go for the other option. Modern compilers are also capable of optimizing this constant so that no storage space is required for it.
The only reason for not using the static const variant is if you want to forbid taking the address of the value: you can't take an address of an enum value while you can take the address of a constant (and this would prompt the compiler to reserve space for the value after all, but only if its address is really taken).
Additionally, the taking of the address will yield a link-time error unless the constant is explicitly defined as well. Notice that it can still be initialized at the site of declaration:
struct foo {
static int const bar = 42; // Declaration, initialization.
};
int const foo::bar; // Definition.
They're not identical:
size_t *pLife1 = &Foo::Life;
size_t *pLife2 = &Bar::Life;
One difference is that the enum defines a type that can be used as a method parameter, for example, to get better type checking. Both are treated as compile time constants by the compiler, so they should generate identical code.
static const values are treated as r-values just like enum in 99% of code you'll see. Constant r-values never have memory generated for them. The advantage enum constants is they can't become l-values in that other 1%. The static const values are type safe and allow for floats, c-strings, etc.
The compiler will make Foo::Life an l-value if it has memory associated with it. The usual way to do that is to take its address. e.g. &Foo::Life;
Here is a subtle example where GCC will use the address:
int foo = rand()? Foo::Life: Foo::Everthing;
The compiler generated code uses the addresses of Life and Everything. Worse, this only produces a linker error about the missing addresses for Foo::Life and Foo::Everything. This behavior is completely standard conforming, though obviously undesirable. There are other compiler specific ways that this can happen, and all standard conforming.
Once you have a conforming c++11 compiler the correct code will be
class Foo {
public:
constexpr size_t Life = 42;
};
This is guaranteed to always be an l-value and it's type-safe, the best of both worlds.
Well, if needed, you can take the address of a static const Member Value. You've have to declare a separate member variable of enum type to take the address of it.
Another third solution?
One subtle difference is that the enum must be defined in the header, and visible for all. When you are avoiding dependencies, this is a pain. For example, in a PImpl, adding an enum is somewhat counter-productive:
// MyPImpl.hpp
class MyImpl ;
class MyPimpl
{
public :
enum { Life = 42 } ;
private :
MyImpl * myImpl ;
}
Another third solution would be a variation on the "const static" alternative proposed in the question: Declaring the variable in the header, but defining it in the source:
// MyPImpl.hpp
class MyImpl ;
class MyPimpl
{
public :
static const int Life ;
private :
MyImpl * myImpl ;
}
.
// MyPImpl.cpp
const int MyPImpl::Life = 42 ;
Note that the value of MyPImpl::Life is hidden from the user of MyPImpl (who includes MyPImpl.hpp).
This will enable the MyPimpl author to change the value of "Life" as needed, without needing the MyPImpl user to recompile, as is the overall aim of the PImpl.