c++ template specialization-specific declaration - c++

Basically, what i'm trying to do is build a Vector template, with two arguments: dimensions, and variable type.
template <typename Type, unsigned ElementCount>
class TVector
{
private:
public:
union
{
struct
{
Type X, Y, Z, W;
};
struct
{
Type Red, Green, Blue, Alpha;
};
Type Values[ElementCount];
};
}
It all works ok, but as you may have noticed, this is only for 4-element vectors, since only the Values variable is dependent on ElementCount. ElementCount=1 declares only X and Red, 2 declares Y and Green, and so on...
So, what i wanted was to have the other variables being declared also depending on the ElementCount value.
Is it at all possible? I don't think so, but wanted to make sure, anyway.
I was thinking of declaring that whole union separately and passing it along as a template parameter, but that's ugly as hell....
EDIT:
Dammit. Now i remembered something... What about the constructor-by-value?
The argument count is dependent of the template parameter ElementCount... How to do this?

You could do it with partial specialization. Something like
template<typename T, unsigned N>
struct S
{
union
{
struct
{
T X, Y, Z, W;
};
struct
{
T Red, Green, Blue, Alpha;
};
T Values[N];
};
};
template<typename T>
struct S<T, 1>
{
union
{
struct
{
T X;
};
struct
{
T Red;
};
T Values[1];
};
};
int main()
{
using S1 = S<char, 1>;
using S5 = S<char, 5>;
std::cout << "sizeof(S1) = " << sizeof(S1) << '\n';
std::cout << "sizeof(S5) = " << sizeof(S5) << '\n';
}
It should print
sizeof(S1) = 1
sizeof(S5) = 5
Also, doing e.g.
S1 s1;
s1.Y = 0;
should give you an error that the structure have no member Y.
Yes it's a lot more to write (or copy-paste) but it should solve your problem.

You don't need to pass in the whole union -- just the struct and the type of the fields. I've also added a syntactic sugar in operator-> so you don't have to reference the .Names part if you don't wish.
#include <iostream>
struct PointStruct {
int X;
int Y;
int Z;
};
struct ColorStruct {
int Red;
int Green;
int Blue;
int Alpha;
};
template <typename Type, typename Struct>
class TVector
{
public:
const static int LEN = sizeof(Struct) / sizeof(Type);
union
{
Struct Names;
Type Values[LEN];
};
Struct* operator->() { return &Names; }
const Struct* operator->() const { return &Names; }
};
int main(int argc, const char** argv) {
TVector < int, PointStruct > points;
points.Names.X = 55;
points.Names.Y = -67;
points.Names.Z = 42;
for (int x = 0; x < points.LEN; ++x) {
std::cout << "points[" << x << "]: " << points.Values[x] << std::endl;
}
points.Values[1] = 135;
std::cout << "points->Y: " << points->Y << std::endl;
TVector < int, ColorStruct > colors;
colors.Names.Red = 1;
colors.Names.Green = 2;
colors.Names.Blue = 3;
colors.Names.Alpha = 4;
for (int x = 0; x < colors.LEN; ++x) {
std::cout << "colors[" << x << "]: " << colors.Values[x] << std::endl;
}
}
With g++ 4.3 I get
points[0]: 55
points[1]: -67
points[2]: 42
points->Y: 135
colors[0]: 1
colors[1]: 2
colors[2]: 3
colors[3]: 4

I would avoid specialization at this level, rather do it inside the union itself:
template <typename T> struct X { T x; };
template <typename T> struct XY { T x, y; };
...
template <typename T, int Count>
struct CountToXYZWType {};
template <typename T> struct CountToXYZWType<T,1> { typedef X<T> type; };
template <typename T> struct CountToXYZWType<T,2> { typedef XY<T> type; };
...
template <typename T, int Count>
struct TVector {
union {
typename CountToXYZWType<Count>::type;
// similarly CountToColorType<Count> ...
T values[Count];
}
...
};

Ok, first of all, a big thank you for everyone, for all the ideas. I finally managed to do what i wanted, using a mix of all you suggested.
second, let me explain, then. I wanted to rewrite my math library. I basically had a class for 2d, 3d and 4d vectors each. It was stupid, since most of the code is the same, so i decided to try to refactor using templates.
I also had a small class named RGB and another called RGBA for obvious reasons :).
And as such, i embarked on this adventure with templates ( i'm not a big fan, but mainly because i can't understand them. they're certainly very useful ).
So, after several failed tries, I changed approach. The final result is a mix of all the above and the kitchen sync. A small taste, including member functions ( i had some trouble with those ), the union with the named member variables is available here: http://goo.gl/4Zlt20
Now, for one final question, if i may...
It all works the way i want it, but for some reason, i can't get rid of that "this->" on the inline functions. Can anyone explain why?
Thanks.

Related

Template (de)activated member variables

I am looking for a convenient to create a C++ class where some member variables are only present if a template flag is set. As a simple example, let's assume I want to toggle an averageSum in an performance sensitive calculation, i.e.
struct Foo {
// Some data and functions..
void operator+=(const Foo& _other) {}
};
template<bool sumAverages>
class Calculator {
public:
// Some member variables...
// Those should only be present if sumAverages is true
int count = 0;
Foo resultSum;
void calculate(/* some arguments */) {
// Calculation of result...
Foo result;
// This should only be calculated if sumAverages is true
++count;
resultSum += result;
// Possibly some post processing...
}
};
One way would be using preprocessor defines, but those are rather inconvenient especially if I need both versions in the same binary. So I am looking for an alternative using templates and if constexpr and something like the following Conditional class:
template<bool active, class T>
struct Conditional;
template<class T>
struct Conditional<true, T> : public T {};
template<class T>
struct Conditional<false, T> {};
My first shot was this:
template<bool sumAverages>
class Calculator {
public:
int count = 0;
Conditional<sumAverages, Foo> resultSum;
void calculate(/* some arguments */) {
Foo result;
if constexpr(sumAverages) {
++count;
resultSum += result;
}
}
};
The if constexpr should incur no run time cost and as it is dependent on a template variable should allow non-compiling code in the false case (e.g. in this example Conditional<false, Foo> does not define a += operator, still it compiles). So this part is more or less perfect. However the variables count and resultSum are still somewhat present. In particular, as one can not derive from a fundamental type, the Conditional class does not allow to toggle the int dependent on the template. Furthermore every Conditional<false, T> variable still occupies one byte possibly bloating small classes. This could be solvable by the new [[no_unique_address]] attribute, however my current compiler chooses to ignore it in all my tests, still using at leas one byte per variable.
To improve things I tried inheriting the variables like this
struct OptionalMembers {
int count;
Foo resultSum;
};
template<bool sumAverages>
class Calculator : public Conditional<sumAverages, OptionalMembers> {
public:
void calculate(/* some arguments */) {
Foo result;
if constexpr(sumAverages) {
++OptionalMembers::count;
OptionalMembers::resultSum += result;
}
}
};
This should come at no space cost as inheriting from am empty class should do literally nothing, right? A possible disadvantage is that one cannot freely set the order of the variables (the inherited variables always come first).
My questions are:
Do you see any problems using the approaches described above?
Are there better options to de(activate) variables like this?
There are a different ways to solve this, one straightforward one would be using template specialization:
#include <iostream>
template <bool b> struct Calculator {
int calculate(int i, int j) { return i + j; }
};
template <> struct Calculator<true> {
int sum;
int calculate(int i, int j) { return sum = i + j; }
};
int main(int argc, char **argv) {
Calculator<false> cx;
cx.calculate(3, 4);
/* std::cout << cx.sum << '\n'; <- will not compile */
Calculator<true> cy;
cy.calculate(3, 4);
std::cout << cy.sum << '\n';
return 0;
}
Another solution would be to use mixin-like types to add features to your calculator type:
#include <iostream>
#include <type_traits>
struct SumMixin {
int sum;
};
template <typename... Mixins> struct Calculator : public Mixins... {
int calculate(int i, int j) {
if constexpr (is_deriving_from<SumMixin>()) {
return SumMixin::sum = i + j;
} else {
return i + j;
}
}
private:
template <typename Mixin> static constexpr bool is_deriving_from() {
return std::disjunction_v<std::is_same<Mixin, Mixins>...>;
}
};
int main(int argc, char **argv) {
Calculator<> cx;
cx.calculate(3, 4);
/* std::cout << cx.sum << '\n'; <- will not compile */
Calculator<SumMixin> cy;
cy.calculate(3, 4);
std::cout << cy.sum << '\n';
return 0;
}

make vector 3D derived from vector ND, need to retain field x y z

I have a vector 3D class
class Vector3D{
public: float x; float y; float z;
//some functions, e.g. operator+ - * /
//some 3D-specific function
};
and a vector N-D class.
template<int constSize> class VecFloatFix{
float database[constSize];
//some functions, e.g. operator+ - * /
};
I noticed that there is code-duplication between two classes, so I think I should make Vector3D derived from VecFloatFix<3> :-
class Vector3D : public VecFloatFix<3>{
//some 3D-specific function
};
Everything seems to be good, except that there are a lot of user code access Vector3D::x,y,z directly.
Is it possible to make Vector3D derived from VecFloatFix<3> while not break user's code?
My best guess is around :-
template<int constSize> class VecFloatFix{
union{
float database[constSize];
float x,y,z; ????? sound like a hack
}
//some functions, e.g. operator+ - * /
};
Edit: Hardcoding x,y,z into VecFloatFix is unsustainable.
If I have a new class Vector2D that derived from VecFloatFix<2>, Vector2D::z will compile fine (dangerous).
Here is a version that only exposes x, y, z components for vectors of size 3. Obviously other sizes may also be specialized.
template<int constSize> struct VecFloatStorage
{
float database[constSize];
};
template<> struct VecFloatStorage<3>
{
union
{
float database[3];
struct { float x, y, z; };
};
};
template<int constSize> class VecFloatFix : public VecFloatStorage<constSize>
{
public:
// Methods go here.
};
I don't know if the standard guarantees struct { float x, y, z; } to have the same memory layout as float data[3], however in practice I am pretty certain that assumption holds.
The GLM library is using a similar trick, except they don't have an array member at all, instead providing an indexing operator that returns (&this->x)[idx].
This is by no ways guaranteed to work as it uses implementation-defined and possibly undefined behaviour. A sensible implementation will probably behave as expected though.
template<int constSize>
class VecFloatFix{
public:
union {
float database[constSize];
struct {
int x, y, z;
};
};
};
This also leaves database public. Don't see a way around this, but no big deal since you provide operator[] anyway.
This assumes constSize >= 3. If you need smaller sizes, this is doable through a bit more hackery. All vectors will have x y and z members but only 3D and above will have them all usable. The 2D vector will have only x and y usable (any use of z is likely to result in an error) and the 1D vector will have just x. Note I refuse to take responsibility for any of the following.
template<int constSize>
class VecFloatFix{
public:
union {
float database[constSize];
struct {
float x;
};
struct {
spacer<constSize, 1> sp1;
typename spacer<constSize, 1>::type y;
};
struct {
spacer<constSize, 2> sp2;
typename spacer<constSize, 2>::type z;
};
};
};
where spacer is defined this way:
template <int N, int M, bool enable>
struct filler;
template <int N, int M>
struct filler<N, M, true>
{
float _f[M];
typedef float type;
};
template <int N, int M>
struct filler<N, M, false>
{
struct nothing {};
typedef nothing type;
};
template <int N, int M>
struct spacer
{
filler<N, M, (N>M)> _f;
typedef typename filler<N, M, (N>M)>::type type;
};
Test drive:
VecFloatFix<4> vec4;
VecFloatFix<3> vec3;
VecFloatFix<2> vec2;
VecFloatFix<1> vec1;
`smoke test`
vec3.database[0] = 42;
vec2.database[1] = 99;
std::cout << vec3.x << std::endl;
std::cout << vec2.y << std::endl;
// make sure `y` aliases `database[1]`
std::cout << & vec2.y << std::endl;
std::cout << & vec2.database[1] << std::endl;
// make sure sizes are as expected
std::cout << sizeof(vec4) << " " << sizeof (vec3) << " " << sizeof(vec2) << " " << sizeof(vec1) << std::endl;

How to traverse all fields of C++ class? [duplicate]

This question already has answers here:
Iterating over a struct in C++
(8 answers)
Closed 1 year ago.
Is it possible in C++ to iterate through a Struct or Class to find all of its members? For example, if I have struct a, and class b:
struct a
{
int a;
int b;
int c;
}
class b
{
public:
int a;
int b;
private:
int c;
}
Would it be possible to loop them to say get a print statement saying "Struct a has int named a, b, c" or "Class b has int named a, b, c"
There are a couple of ways to do this, but you need to use some macros to either define or adapt the struct.
You can use the REFLECTABLE macro given in this answer to define the struct like this:
struct A
{
REFLECTABLE
(
(int) a,
(int) b,
(int) c
)
};
And then you can iterate over the fields and print each value like this:
struct print_visitor
{
template<class FieldData>
void operator()(FieldData f)
{
std::cout << f.name() << "=" << f.get() << std::endl;
}
};
template<class T>
void print_fields(T & x)
{
visit_each(x, print_visitor());
}
A x;
print_fields(x);
Another way is to adapt the struct as a fusion sequence (see the documentation). Here's an example:
struct A
{
int a;
int b;
int c;
};
BOOST_FUSION_ADAPT_STRUCT
(
A,
(int, a)
(int, b)
(int, c)
)
Then you can print the fields as well using this:
struct print_visitor
{
template<class Index, class C>
void operator()(Index, C & c)
{
std::cout << boost::fusion::extension::struct_member_name<C, Index::value>::call()
<< "="
<< boost:::fusion::at<Index>(c)
<< std::endl;
}
};
template<class C>
void print_fields(C & c)
{
typedef boost::mpl::range_c<int,0, boost::fusion::result_of::size<C>::type::value> range;
boost::mpl::for_each<range>(boost::bind<void>(print_visitor(), boost::ref(c), _1));
}
No, it's not possible, because there is no reflection in C++.
If you have members of the same type (as you do in your first specific example) that you want to both (a) have names, and (b) be iterable, then you can combine an array with an enum:
enum names { alice, bob, carl };
struct myStruct;
{
std::array<int, 3> members;
}
Then you can both
myStruct instance;
// iterate through them...
for (auto elem : instance.members)
{
// work with each element in sequence
}
// and call them by name, taking away the need to remember which element is the first, etc.
instance.members[bob] = 100;
Clearly not a general solution, but I've found this useful in my own work.
Provided your member variables are of the same type, you can do something like this that i stole from the GLM library:
class Point
{
Point();// you must re-implement the default constructor if you need one
union
{
struct
{
double x;
double y;
double z;
};
std::array<double, 3> components;
};
};
Admittedly this isn't the most elegant solution from a maintainability standpoint, manually keeping count of the number of variables you have is asking for trouble. However It will work without additional libraries or macros and is applicable in most situations that you'd want this behaviour.
Unions don't support automatically generated default constructors so you'll need to write one that tells the object how to initialise the union.
for (double component : point.components)
{
// do something
}
Assuming that all class members are of the same type, you may employ a C++17 feature called structured binding. Assuming that all members are public this would work:
struct SI
{
int x;
int y;
int z;
};
struct SD
{
double x;
double y;
double z;
};
template<typename T>
void print(const T &val)
{
const auto& [a, b, c] = val;
for (auto elem : {a, b, c})
{
std::cout << elem << " ";
}
std::cout << std::endl;
}
This would work with any struct that has exactly 3 public elements of the same (copyable) type. In case of non-public members the function must be a friend or a member. This approach however cannot be easily extented to arbitrary number of elements.
This is an improved version of QCTDevs answer:
class MyClass
{
union
{
struct Memberstruct
{
double test0;
double test1;
double test2;
} m;
array<double, sizeof( Memberstruct ) / sizeof( double )> memberarray;
};
bool test() { &(m.test1) == &(memberarray[1]); }
};
The requirement is still to have all the same datatypes, and you also need to implement the default Constructor, if needed.
It is improved in that you don't need to manually maintain the size of the array.
A drawback is an altered syntax in comparison to the class without this workaround.

Iterate through Struct and Class Members [duplicate]

This question already has answers here:
Iterating over a struct in C++
(8 answers)
Closed 1 year ago.
Is it possible in C++ to iterate through a Struct or Class to find all of its members? For example, if I have struct a, and class b:
struct a
{
int a;
int b;
int c;
}
class b
{
public:
int a;
int b;
private:
int c;
}
Would it be possible to loop them to say get a print statement saying "Struct a has int named a, b, c" or "Class b has int named a, b, c"
There are a couple of ways to do this, but you need to use some macros to either define or adapt the struct.
You can use the REFLECTABLE macro given in this answer to define the struct like this:
struct A
{
REFLECTABLE
(
(int) a,
(int) b,
(int) c
)
};
And then you can iterate over the fields and print each value like this:
struct print_visitor
{
template<class FieldData>
void operator()(FieldData f)
{
std::cout << f.name() << "=" << f.get() << std::endl;
}
};
template<class T>
void print_fields(T & x)
{
visit_each(x, print_visitor());
}
A x;
print_fields(x);
Another way is to adapt the struct as a fusion sequence (see the documentation). Here's an example:
struct A
{
int a;
int b;
int c;
};
BOOST_FUSION_ADAPT_STRUCT
(
A,
(int, a)
(int, b)
(int, c)
)
Then you can print the fields as well using this:
struct print_visitor
{
template<class Index, class C>
void operator()(Index, C & c)
{
std::cout << boost::fusion::extension::struct_member_name<C, Index::value>::call()
<< "="
<< boost:::fusion::at<Index>(c)
<< std::endl;
}
};
template<class C>
void print_fields(C & c)
{
typedef boost::mpl::range_c<int,0, boost::fusion::result_of::size<C>::type::value> range;
boost::mpl::for_each<range>(boost::bind<void>(print_visitor(), boost::ref(c), _1));
}
No, it's not possible, because there is no reflection in C++.
If you have members of the same type (as you do in your first specific example) that you want to both (a) have names, and (b) be iterable, then you can combine an array with an enum:
enum names { alice, bob, carl };
struct myStruct;
{
std::array<int, 3> members;
}
Then you can both
myStruct instance;
// iterate through them...
for (auto elem : instance.members)
{
// work with each element in sequence
}
// and call them by name, taking away the need to remember which element is the first, etc.
instance.members[bob] = 100;
Clearly not a general solution, but I've found this useful in my own work.
Provided your member variables are of the same type, you can do something like this that i stole from the GLM library:
class Point
{
Point();// you must re-implement the default constructor if you need one
union
{
struct
{
double x;
double y;
double z;
};
std::array<double, 3> components;
};
};
Admittedly this isn't the most elegant solution from a maintainability standpoint, manually keeping count of the number of variables you have is asking for trouble. However It will work without additional libraries or macros and is applicable in most situations that you'd want this behaviour.
Unions don't support automatically generated default constructors so you'll need to write one that tells the object how to initialise the union.
for (double component : point.components)
{
// do something
}
Assuming that all class members are of the same type, you may employ a C++17 feature called structured binding. Assuming that all members are public this would work:
struct SI
{
int x;
int y;
int z;
};
struct SD
{
double x;
double y;
double z;
};
template<typename T>
void print(const T &val)
{
const auto& [a, b, c] = val;
for (auto elem : {a, b, c})
{
std::cout << elem << " ";
}
std::cout << std::endl;
}
This would work with any struct that has exactly 3 public elements of the same (copyable) type. In case of non-public members the function must be a friend or a member. This approach however cannot be easily extented to arbitrary number of elements.
This is an improved version of QCTDevs answer:
class MyClass
{
union
{
struct Memberstruct
{
double test0;
double test1;
double test2;
} m;
array<double, sizeof( Memberstruct ) / sizeof( double )> memberarray;
};
bool test() { &(m.test1) == &(memberarray[1]); }
};
The requirement is still to have all the same datatypes, and you also need to implement the default Constructor, if needed.
It is improved in that you don't need to manually maintain the size of the array.
A drawback is an altered syntax in comparison to the class without this workaround.

Compile-time constant id

Given the following:
template<typename T>
class A
{
public:
static const unsigned int ID = ?;
};
I want ID to generate a unique compile time ID for every T. I've considered __COUNTER__ and the boost PP library but have been unsuccessful so far. How can I achieve this?
Edit: ID has to be usable as the case in a switch statement
Edit2: All the answers based on the address of a static method or member are incorrect. Although they do create a unique ID they are not resolved in compile time and therefore can not be used as the cases of a switch statement.
This is sufficient assuming a standards conforming compiler (with respect to the one definition rule):
template<typename T>
class A
{
public:
static char ID_storage;
static const void * const ID;
};
template<typename T> char A<T>::ID_storage;
template<typename T> const void * const A<T>::ID= &A<T>::ID_storage;
From the C++ standard 3.2.5 One definition rule [basic.def.odr] (bold emphasis mine):
... If D is a template and is defined in more than one translation
unit, then the last four requirements from the list above shall apply
to names from the template’s enclosing scope used in the template
definition (14.6.3), and also to dependent names at the point of
instantiation (14.6.2). If the definitions of D satisfy all these
requirements, then the program shall behave as if there were a single
definition of D. If the definitions of D do not satisfy these
requirements, then the behavior is undefined.
What I usually use is this:
template<typename>
void type_id(){}
using type_id_t = void(*)();
Since every instantiation of the function has it's own address, you can use that address to identify types:
// Work at compile time
constexpr type_id_t int_id = type_id<int>;
// Work at runtime too
std::map<type_id_t, std::any> types;
types[type_id<int>] = 4;
types[type_id<std::string>] = "values"s
// Find values
auto it = types.find(type_id<int>);
if (it != types.end()) {
// Found it!
}
It is possible to generate a compile time HASH from a string using the code from this answer.
If you can modify the template to include one extra integer and use a macro to declare the variable:
template<typename T, int ID> struct A
{
static const int id = ID;
};
#define DECLARE_A(x) A<x, COMPILE_TIME_CRC32_STR(#x)>
Using this macro for the type declaration, the id member contains a hash of the type name. For example:
int main()
{
DECLARE_A(int) a;
DECLARE_A(double) b;
DECLARE_A(float) c;
switch(a.id)
{
case DECLARE_A(int)::id:
cout << "int" << endl;
break;
case DECLARE_A(double)::id:
cout << "double" << endl;
break;
case DECLARE_A(float)::id:
cout << "float" << endl;
break;
};
return 0;
}
As the type name is converted to a string, any modification to the type name text results on a different id. For example:
static_assert(DECLARE_A(size_t)::id != DECLARE_A(std::size_t)::id, "");
Another drawback is due to the possibility for a hash collision to occur.
This seems to work OK for me:
template<typename T>
class Counted
{
public:
static int id()
{
static int v;
return (int)&v;
}
};
#include <iostream>
int main()
{
std::cout<<"Counted<int>::id()="<<Counted<int>::id()<<std::endl;
std::cout<<"Counted<char>::id()="<<Counted<char>::id()<<std::endl;
}
Use the memory address of a static function.
template<typename T>
class A {
public:
static void ID() {}
};
(&(A<int>::ID)) will be different from (&(A<char>::ID)) and so on.
Using this constant expression counter:
template <class T>
class A
{
public:
static constexpr int ID() { return next(); }
};
class DUMMY { };
int main() {
std::cout << A<char>::ID() << std::endl;
std::cout << A<int>::ID() << std::endl;
std::cout << A<BETA>::ID() << std::endl;
std::cout << A<BETA>::ID() << std::endl;
return 0;
}
output: (GCC, C++14)
1
2
3
3
The downside is you will need to guess an upper bound on the number of derived classes for the constant expression counter to work.
I encountered this exact problem recently.
My solution:
counter.hpp
class counter
{
static int i;
static nexti()
{
return i++;
}
};
Counter.cpp:
int counter::i = 0;
templateclass.hpp
#include "counter.hpp"
template <class T>
tclass
{
static const int id;
};
template <class T>
int tclass<T>::id = counter::nexti();
It appers to work properly in MSVC and GCC, with the one exception that you can't use it in a switch statement.
For various reasons I actually went further, and defined a preprocessor macro that creates a new class from a given name parameter with a static ID (as above) that derives from a common base.
Here is a possible solution mostly based on templates:
#include<cstddef>
#include<functional>
#include<iostream>
template<typename T>
struct wrapper {
using type = T;
constexpr wrapper(std::size_t N): N{N} {}
const std::size_t N;
};
template<typename... T>
struct identifier: wrapper<T>... {
template<std::size_t... I>
constexpr identifier(std::index_sequence<I...>): wrapper<T>{I}... {}
template<typename U>
constexpr std::size_t get() const { return wrapper<U>::N; }
};
template<typename... T>
constexpr identifier<T...> ID = identifier<T...>{std::make_index_sequence<sizeof...(T)>{}};
// ---
struct A {};
struct B {};
constexpr auto id = ID<A, B>;
int main() {
switch(id.get<B>()) {
case id.get<A>():
std::cout << "A" << std::endl;
break;
case id.get<B>():
std::cout << "B" << std::endl;
break;
}
}
Note that this requires C++14.
All you have to do to associate sequential ids to a list of types is to provide that list to a template variable as in the example above:
constexpr auto id = ID<A, B>;
From that point on, you can get the given id for the given type by means of the get method:
id.get<A>()
And that's all. You can use it in a switch statement as requested and as shown in the example code.
Note that, as long as types are appended to the list of classes to which associate a numeric id, identifiers are the same after each compilation and during each execution.
If you want to remove a type from the list, you can still use fake types as placeholders, as an example:
template<typename> struct noLonger { };
constexpr auto id = ID<noLonger<A>, B>;
This will ensure that A has no longer an associated id and the one given to B won't change.
If you won't to definitely delete A, you can use something like:
constexpr auto id = ID<noLonger<void>, B>;
Or whatever.
Ok.....so this is a hack that I found from this website. It should work. The only thing you need to do is add another template parameter to your struct that takes a counter "meta-object". Note that A with int, bool and char all have unique IDs, but it is not guaranteed that int's will be 1 and bool will be 2, etc., because the order in which templates are initiated is not necessarily known.
Another note:
This will not work with Microsoft Visual C++
#include <iostream>
#include "meta_counter.hpp"
template<typename T, typename counter>
struct A
{
static const size_t ID = counter::next();
};
int main () {
typedef atch::meta_counter<void> counter;
typedef A<int,counter> AInt;
typedef A<char,counter> AChar;
typedef A<bool,counter> ABool;
switch (ABool::ID)
{
case AInt::ID:
std::cout << "Int\n";
break;
case ABool::ID:
std::cout << "Bool\n";
break;
case AChar::ID:
std::cout << "Char\n";
break;
}
std::cout << AInt::ID << std::endl;
std::cout << AChar::ID << std::endl;
std::cout << ABool::ID << std::endl;
std::cout << AInt::ID << std::endl;
while (1) {}
}
Here is meta_counter.hpp:
// author: Filip Roséen <filip.roseen#gmail.com>
// source: http://b.atch.se/posts/constexpr-meta-container
#ifndef ATCH_META_COUNTER_HPP
#define ATCH_META_COUNTER_HPP
#include <cstddef>
namespace atch { namespace {
template<class Tag>
struct meta_counter {
using size_type = std::size_t;
template<size_type N>
struct ident {
friend constexpr size_type adl_lookup (ident<N>);
static constexpr size_type value = N;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<class Ident>
struct writer {
friend constexpr size_type adl_lookup (Ident) {
return Ident::value;
}
static constexpr size_type value = Ident::value;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<size_type N, int = adl_lookup (ident<N> {})>
static constexpr size_type value_reader (int, ident<N>) {
return N;
}
template<size_type N>
static constexpr size_type value_reader (float, ident<N>, size_type R = value_reader (0, ident<N-1> ())) {
return R;
}
static constexpr size_type value_reader (float, ident<0>) {
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<size_type Max = 64>
static constexpr size_type value (size_type R = value_reader (0, ident<Max> {})) {
return R;
}
template<size_type N = 1, class H = meta_counter>
static constexpr size_type next (size_type R = writer<ident<N + H::value ()>>::value) {
return R;
}
};
}}
#endif /* include guard */
using template and if constexpr, need c++17
#include <iostream>
template <typename Type, typename... Types>
struct TypeRegister{
template<typename Queried_type>
static constexpr int id(){
if constexpr (std::is_same_v<Type, Queried_type>) return 0;
else{
static_assert((sizeof...(Types) > 0), "You shan't query a type you didn't register first");
return 1 + TypeRegister<Types...>::template id<Queried_type>();
}
}
};
int main(){
using reg_map = TypeRegister<int, float, char, const int&>;
std::cout << reg_map::id<const int&>() << std::endl;// 3
// std::cout << reg_map::id<const int>() << std::endl;// error
}
This can't be done. An address to a static object is the closest you can get to a unique id, however in order to take addresses of such objects (even static const integrals) they must be defined somewhere. Per the one definition rule, they should be defined within a CPP file, which cannot be done since they are templates. If you define the statics within a header file, then each compilation unit will get its own version of it implemented of course at different addresses.
I had a similar problem a few months ago. I was looking for a technique to define identifiers that are the same over each execution.
If this is a requirement, here is another question that explores more or less the same issue (of course, it comes along with its nice answer).
Anyway I didn't use the proposed solution. It follows a description of what I did that time.
You can define a constexpr function like the following one:
static constexpr uint32_t offset = 2166136261u;
static constexpr uint32_t prime = 16777619u;
constexpr uint32_t fnv(uint32_t partial, const char *str) {
return str[0] == 0 ? partial : fnv((partial^str[0])*prime, str+1);
}
inline uint32_t fnv(const char *str) {
return fnv(offset, str);
}
Then a class like this from which to inherit:
template<typename T>
struct B {
static const uint32_t id() {
static uint32_t val = fnv(T::identifier);
return val;
}
};
CRTP idiom does the rest.
As an example, you can define a derived class as it follows:
struct C: B<C> {
static const char * identifier;
};
const char * C::identifier = "ID(C)";
As long as you provide different identifiers for different classes, you will have unique numeric values that can be used to distinguish between the types.
Identifiers are not required to be part of the derived classes. As an example, you can provide them by means of a trait:
template<typename> struct trait;
template<> struct trait { static const char * identifier; };
// so on with all the identifiers
template<typename T>
struct B {
static const uint32_t id() {
static uint32_t val = fnv(trait<T>::identifier);
return val;
}
};
Advantages:
Easy to implement.
No dependencies.
Numeric values are the same during each execution.
Classes can share the same numeric identifier if needed.
Disadvantages:
Error-prone: copy-and-paste can quickly become your worst enemy.
It follows a minimal, working example of what has been described above.
I adapted the code so as to be able to use the ID member method in a switch statement:
#include<type_traits>
#include<cstdint>
#include<cstddef>
static constexpr uint32_t offset = 2166136261u;
static constexpr uint32_t prime = 16777619u;
template<std::size_t I, std::size_t N>
constexpr
std::enable_if_t<(I == N), uint32_t>
fnv(uint32_t partial, const char (&)[N]) {
return partial;
}
template<std::size_t I, std::size_t N>
constexpr
std::enable_if_t<(I < N), uint32_t>
fnv(uint32_t partial, const char (&str)[N]) {
return fnv<I+1>((partial^str[I])*prime, str);
}
template<std::size_t N>
constexpr inline uint32_t fnv(const char (&str)[N]) {
return fnv<0>(offset, str);
}
template<typename T>
struct A {
static constexpr uint32_t ID() {
return fnv(T::identifier);
}
};
struct C: A<C> {
static constexpr char identifier[] = "foo";
};
struct D: A<D> {
static constexpr char identifier[] = "bar";
};
int main() {
constexpr auto val = C::ID();
switch(val) {
case C::ID():
break;
case D::ID():
break;
default:
break;
}
}
Please, note that if you want to use ID in a non-constant expression, you must define somewhere the identifiers as it follows:
constexpr char C::identifier[];
constexpr char D::identifier[];
Once you did it, you can do something like this:
int main() {
constexpr auto val = C::ID();
// Now, it is well-formed
auto ident = C::ID();
// ...
}
Here is a C++ code that uses __DATE__ and __TIME__ macro to get unique identifiers for types <T>
Format:
// __DATE__ "??? ?? ????"
// __TIME__ "??:??:??"
This is a poor quality hash function:
#define HASH_A 8416451
#define HASH_B 11368711
#define HASH_SEED 9796691 \
+ __DATE__[0x0] * 389 \
+ __DATE__[0x1] * 82421 \
+ __DATE__[0x2] * 1003141 \
+ __DATE__[0x4] * 1463339 \
+ __DATE__[0x5] * 2883371 \
+ __DATE__[0x7] * 4708387 \
+ __DATE__[0x8] * 4709213 \
+ __DATE__[0x9] * 6500209 \
+ __DATE__[0xA] * 6500231 \
+ __TIME__[0x0] * 7071997 \
+ __TIME__[0x1] * 10221293 \
+ __TIME__[0x3] * 10716197 \
+ __TIME__[0x4] * 10913537 \
+ __TIME__[0x6] * 14346811 \
+ __TIME__[0x7] * 15485863
unsigned HASH_STATE = HASH_SEED;
unsigned HASH() {
return HASH_STATE = HASH_STATE * HASH_A % HASH_B;
}
Using the hash function:
template <typename T>
class A
{
public:
static const unsigned int ID;
};
template <>
const unsigned int A<float>::ID = HASH();
template <>
const unsigned int A<double>::ID = HASH();
template <>
const unsigned int A<int>::ID = HASH();
template <>
const unsigned int A<short>::ID = HASH();
#include <iostream>
int main() {
std::cout << A<float>::ID << std::endl;
std::cout << A<double>::ID << std::endl;
std::cout << A<int>::ID << std::endl;
std::cout << A<short>::ID << std::endl;
}
If non-monotonous values and an intptr_t are acceptable:
template<typename T>
struct TypeID
{
private:
static char id_ref;
public:
static const intptr_t ID;
};
template<typename T>
char TypeID<T>::id_ref;
template<typename T>
const intptr_t TypeID<T>::ID = (intptr_t)&TypeID<T>::id_ref;
If you must have ints, or must have monotonically incrementing values, I think using static constructors is the only way to go:
// put this in a namespace
extern int counter;
template<typename T>
class Counter {
private:
Counter() {
ID_val = counter++;
}
static Counter init;
static int ID_val;
public:
static const int &ID;
};
template<typename T>
Counter<T> Counter<T>::init;
template<typename T>
int Counter<T>::ID_val;
template<typename T>
const int &Counter<T>::ID = Counter<T>::ID_val;
// in a non-header file somewhere
int counter;
Note that neither of these techniques is safe if you are sharing them between shared libraries and your application!
Another alternative is to consider the following class Data with the unique, static member field type:
template <class T>
class Data
{
public:
static const std::type_index type;
};
// do [static data member initialization](http://stackoverflow.com/q/11300652/3041008)
// by [generating unique type id](http://stackoverflow.com/q/26794944/3041008)
template <class T>
std::type_index const Data<T>::type = std::type_index(typeid(T));
produces the output (MinGWx64-gcc4.8.4 -std=c++11 -O2)
printf("%s %s\n", Data<int>::type.name(), Data<float>::type.name())
//prints "i f"
It's not exactly an integer id or pretty-printable string, nor a constexpr, but can be used as an index in (un)ordered associative containers.
It also appears to work if the Data.h header is included in multiple files (same hashCode() values).
Here is a pragmatic solution, if you are ok with writing a single additional line DECLARE_ID(type) for each type you want to use:
#include <iostream>
template<class> struct my_id_helper;
#define DECLARE_ID(C) template<> struct my_id_helper<C> { enum {value = __COUNTER__ }; }
// actually declare ids:
DECLARE_ID(int);
DECLARE_ID(double);
// this would result in a compile error: redefinition of struct my_id_helper<int>’
// DECLARE_ID(int);
template<class T>
class A
{
public:
static const unsigned int ID = my_id_helper<T>::value;
};
int main()
{
switch(A<int>::ID)
{
case A<int>::ID: std::cout << "it's an int!\n"; break;
case A<double>::ID: std::cout << "it's a double!\n"; break;
// case A<float>::ID: // error: incomplete type ‘my_id_helper<float>’
default: std::cout << "it's something else\n"; break;
}
}
template<typename T>
static void get_type_id() { void* x; new (x) T(); }
using type_id_t = void(*)();
works fine with optimizations