How to convert a struct into a template parameter pack? - c++

Ok suppose I have a struct like so:
struct Example{
uint8_t var0;
uint32_t var1;
uint16_t var2;
};
And suppose I have an instance (note constexpr) of the class that looks like this:
constexpr Example exp = {10,11,12};
And I want to somehow get the bit representation of this into a template parameter pack.
An example of what this would look like:
typedef SomeTemplate<
/* first variable: 1 byte */ 10,
/* second variable: 4 bytes */ 11, 0, 0, 0,
/* third variable: 2 bytes */ 12, 0> mydef;
My knee jerk response to doing this is to do some template meta programming magic with some unions, but unfortunately this is not possible because accessing a union in the way I want is undefined behavior at compile time (ie error).
My ultimate goal with all of this is to put an instance of a user defined type into as a template parameter....something like this:
template<Example exp>
class OtherClass{
};
So the reason I am on this rabbit trail is I could take class Example and give a templated constructor which would take a list of uint8_ts in and then initialize itself that way (thus still constexpr and effectively allowing me to pass it in directly).
So is there any way to convert an arbitrary struct instance into an bit pattern at compile time (and all constexpr)?

Here is what I eventually ended up doing:
template<class T,class... Args_t>
struct Statifier{
constexpr T operator()() { return T(Args_t()...); }
constexpr operator T() { return T(Args_t()...); }
};
And then you use it like so:
template<class T, T value>
using ic = integral_constant<T,value>;
struct Point{
int x;
int y;
int z;
constexpr Point(int x,int y,int z) : x(x),y(y),z(z) { }
};
typedef Statifier<Point,ic<int,12>,ic<int,12>,ic<int,12> > triple;
triple is now a type and can be passed into a template parameter.
Limits of this approach:
You can only use types which can be differentiated by their constructors
You have to use types that have constexpr constructors
It can be cumbersome to initialize
But it is still awesome.
Thanks for you comments....they did help me find this method

Related

How to "whitelist" template specializations?

I am trying to create a type safe abstraction for registers. Shortly explained a register can contain a field of bits which have some special meaning and the bits in question can usually be either set to a range of valid values (specified by an enum) or to any integer value (if so specified). The fields in a single register are described by an enum.
What I am having some trouble with is how do I create a template that allows me to specify the valid combinations that this enum VALUE can only be paired with a) value specified by an enum b) any integer value. The actual set function is the same for any combination (it will cast down to underlying value from the enum class values). Other thing to note is that I'd like the set() method to be generic in a way that it is in a separate file from the actual register definitions so adding static_asserts() there etc. to prevent some type combinations etc. is not a good solution. I have a solution that is very close to what I want but I'm not sure how can I get the template type deduction to work so that I don't need to type the name of the enum type twice per call.
enum class Definitions : uint32_t
{
kBit0 = 1UL << 0,
kBit1 = 1UL << 1,
kField0 = 0xF0,
kField1 = 0xF00,
kField2 = 0xF000
};
enum class Field0Values
{
Setting1 = 0x01,
Setting2 = 0x02,
};
enum class Field1Values
{
Setting1 = 0x01,
Setting2 = 0x02,
};
template<class MaskType, MaskType value> struct allowed_type;
template<> struct allowed_type<Definitions, Definitions::kField0> {
using type = Field0Values;
};
template<> struct allowed_type<Definitions, Definitions::kField1> {
using type = Field1Values;
};
template<> struct allowed_type<Definitions, Definitions::kField2> {
using type = uint32_t;
};
template<class MaskType, MaskType maskValue>
constexpr void set(typename allowed_type<MaskType, maskValue>::type value) {}
int main()
{
// Valid set operations
set<Definitions, Definitions::kField0>(Field0Values::Setting1);
set<Definitions, Definitions::kField1>(Field1Values::Setting1);
set<Definitions, Definitions::kField2>(42);
// Mistakes, will not compile
set<Definitions, Definitions::kField0>(Field1Values::Setting1);
set<Definitions, Definitions::kField1>(Field0Values::Setting1);
set<Definitions, Definitions::kField1>(7);
}
This is nearly what I want except I would like to be able to just say set<Definitions::kField0>(Field0Values::Setting1). I CAN do that if I declare a template specialization like:
template<Definitions mask>
constexpr void set(typename allowed_type<Definitions, mask>::type value);
But the issue with that is that I do not want to provide the implementation for that specialization, I just want it to use the base template function, not sure how can I do that. How can I get the template type deduction to deduce the type without having to create the template specialization?
Also interested if someone has another approach that doesn't have this type deduction issue.
How about setting the template argument to auto in both allowed_type and set?
template<auto value> struct allowed_type;
template<> struct allowed_type<Definitions::kField0> {
using type = Field0Values;
};
template<auto maskValue>
constexpr void set(typename allowed_type<maskValue>::type) {}
Alternatively, if you prefer to keep allowed_type as is, you can also only change set:
template<auto maskValue>
constexpr void set(typename allowed_type<decltype(maskValue), maskValue>::type value) {}

type as returntype in c++

Is there a possibility to return a type as a returntype from a function
and use it for a member variable using something like this:
constexpr type myFunction(int a, int b){
if(a + b == 8) return int_8t;
if(a + b == 16) return int_16t;
if(a + b == 32) return int_32t;
return int_64t;
}
template<int x, int y>
class test{
using type = typename myFunction(x, y);
private:
type m_variable;
};
When trying this example in Qt it says
Error: 'constexpr' does not name a type
Error: 'test' is not a template type
class test{
^
In an earlier question someone showed me http://en.cppreference.com/w/cpp/types/conditional this function, but it works only for 2 Types.
You cannot do this with a normal function. However, it is easily done using template meta-programming. This kind of template is sometimes called a type function.
#include <cstdint>
template<int bits> struct integer { /* empty */ };
// Specialize for the bit widths we want.
template<> struct integer<8> { typedef int8_t type; };
template<> struct integer<16> { typedef int16_t type; };
template<> struct integer<32> { typedef int32_t type; };
It can be used like this.
using integer_type = integer<16>::type;
integer_type number = 42;
Remember to precede integer<T>::type with the typename keyword if T is itself a template parameter.
I leave it as an exercise to you to extend this to a template that accepts two integers as parameters and returns the appropriate type based on the sum of the two.

Changing enum values based on HW selection

What is the best way to design a function where the allowed enum value changes based on the HW selected for example. The function might look like this, this won't compile but hopefully you get the idea.
enum class EHWUnit
{
Unit0,
Unit1,
Unit2
};
enum class EHWType
{
Type1,
Type2,
Type3,
Type4
};
SelectHWinput( const EHWUnit aUnit, const EHWType aHWType, const unit8_t aSelect )
{
if( aHWType & 1 == 0)
ArrayIS( 2,4,6,8,10)
else
ArrayIS( 1,3,5,7,9)
element = ArrayIS(aSelect)
WriteToRegister( Address, bits, element);
}
Does anyone know of a way to make it better to select the element based on type? I would prefer to somehow link those even elements to the type at compile time and not select them at run time, using one function is there anyway to make this code more fool proof?
A shot in the dark, as I'm not sure what exactly it is you want to do.
It seems like you want to make some compile-time decisions, which could look something like this:
enum EHWUnit
{
Unit0,
Unit1,
Unit2
};
enum EHWType
{
Type1,
Type2,
Type3,
Type4
};
template <int Select>
struct ArrayIS
{
static constexpr int const array[] = {1, 3, 5, 7, 9};
};
template <int Select>
constexpr int const ArrayIS<Select>::array[];
template <>
struct ArrayIS<0>
{
static constexpr int const array[] = {2, 4, 6, 8, 10};
};
constexpr int const ArrayIS<0>::array[];
template <EHWUnit aUnit, EHWType aHWType, int aSelect>
struct SelectHWinput
{
static constexpr int get()
{
return ArrayIS<static_cast<int>(aHWType) & 1>::array[aSelect];
}
};
int main()
{
// To illustrate that the value is selected at compile-time, a
// static assertion that will always fail:
static_assert(SelectHWinput<Unit0, Type1, 0>::get() < 0, "Works, value selected at compile-time");
}
In the code above, Template Metaprogramming (TMP) is used to select a value of one of the arrays at compile-time. The correct array is chosen by supplying the Select template non-type parameter. Because these arrays are declared constexpr, a constexpr member-function can be used to extract one of its element at compile-time. The static_assert proves that it works.
If you want to construct the arrays more flexibly at compile-time, I suggest looking at this question of mine, where I describe TMP-functors to construct static arrays at compile-time:
g++ (4.7.2) bug or feature, when initializing static arrays at compile-time?
EDIT:
You said you were interested in the Array implementation:
template <typename T, size_t Count, template <typename, T> class Function, T Current, T ... Elements>
struct Array_: public Array_<T, Count - 1, Function, Function<T, Current>::result, Elements ..., Current>
{};
template <typename T, template <typename, T> class Function, T Current, T ... Elements>
struct Array_<T, 0, Function, Current, Elements...>
{
constexpr static std::array<T, sizeof...(Elements)> array = {{Elements ...}};
};
template <typename T, size_t Count, T Start = T(), template <typename, T> class Function = Null>
struct Array: public Array_<T, Count, Function, Start>
{};
Here, the last one is the one you'll use, using a Template Metaprogramming functor that tells the compiler how to generate the next element from the previous one. This is a limitation, but it's the best I could come up with at the time.
Three simple functors that you could use:
template <typename T, T Value>
struct Null
{
enum { result = Value };
};
template <typename T, T Value>
struct Increment
{
enum { result = Value + 1 };
};
template <typename T, T Value>
struct Decrement
{
enum { result = Value - 1 };
};
For example, if you need an array with incremental values from 1 to 100, you would do this:
std::array<int, 100> arr = Array<int, 100, 1, Increment>::array;
This array is then allocated and populated at compile-time.

compile-time counter for template classes

Imagine that you have a lot of classes with a lot of different template parameters. Every class has a method static void f(). You want to collect all these function pointers in a list L.
A run-time solution would be easy:
typedef void (*p)();
std::vector<p> L;
int reg (p x) { static int i = 0; L.push_back(x); return i++; } // also returns an unique id
template <typename T> struct regt { static int id; };
template <typename T> int regt<T>::id = reg (T::f);
template < typename ... T > struct class1 : regt< class1<T...> > { static void f(); };
template < typename ... T > struct class2 : regt< class2<T...> > { static void f(); };
// etc.
The compiler knows all f()s of all instantiated classes at compile-time. So, theoretically it should be possible to generate such a list (a const std::array<p, S> L with some S) as a compile-time constant list. But how? (C++0x solutions are welcome, too).
Why do I need this?
On an architecture with only 256 kB (for code and data), I need to generate objects for incoming ids of classes. Existing serialization frameworks or the run-time solution above are unnecessarily big. Without templates a compile-time solution would be easy, but I want to keep all the advantages templates offer.
Manually
The simplest thing that you can do is just roll the code manually, I don't think that there is much that can be used to your advantage from the templates, so I will use plain classes, where A, B... stand for particular instantiations of your types. That allows for compile time initialization of the types, at the cost of having to remember to update the lookup table whenever a new type is added to the system:
typedef void (*function_t)();
function_t func[] = {
&A::f,
&B::f,
&C::f
};
I would recommend this, from a maintenance point of view. Automating the system will make the code much harder to understand and maintain in the future.
Macros
The simple most automated one, which will probably generate less code is a macro generation system is just using macros. Since this first approach will use extensive use of macros, I will generate the functions automatically, as you did in the previous question. You can remove that part of code if you have (hopefully) given up the path of full code generation through macros.
To avoid having to retype the names of the types in different contexts you can define a macro with all the data you need for any context, and then use other macros to filter what is to be used (and how) in each particular context:
// This is the actual list of all types, the id and the code that you were
// generating in the other question for the static function:
#define FOREACH_TYPE( macro ) \
macro( A, 0, { std::cout << "A"; } ) \
macro( B, 1, { std::cout << "B"; } ) \
macro( C, 2, { std::cout << "C"; } )
// Now we use that recursive macro to:
// Create an enum and calculate the number of types used
#define ENUM_ITEM( type, id, code ) \
e_##type,
enum AllTypes {
FOREACH_TYPE( ENUM_ITEM )
AllTypes_count
};
#undef ENUM_ITEM
// Now we can create an array of function pointers
typedef void (*function_t)();
function_t func[ AllTypes_count ];
// We can create all classes:
#define CREATE_TYPE( type, the_id, code ) \
struct type {\
static const int id = the_id; \
static void func() code\
};
FOREACH_TYPE( CREATE_TYPE )
#undef CREATE_TYPE
// And create a function that will
#define REGISTER_TYPE( type, id, code ) \
func[ i++ ] = &type::func;
void perform_registration() {
int i = 0;
FOREACH_TYPE( REGISTER_TYPE );
};
#undef REGISTER_TYPE
// And now we can test it
int main() {
perform_registration();
for ( int i = 0; i < AllTypes_count; ++i ) {
func[ i ]();
}
}
This is, on the other hand a maintenance nightmare, quite fragile and hard to debug. Adding new types is trivial, just add a new line to the FOREACH_TYPE macro and you are done... and the best of lucks once something fails...
Templates and metaprogramming
On the other hand, using templates you can get close but you cannot get to the single point of definition for the types. You can automate some of the operations in different ways, but at the very least you will need to define the types themselves and add them to a typelist to get the rest of the functionality.
Simplifying the definition of the actual type_list with C++0x code you can start by defining the types and then creating the type_list. If you want to avoid using C++0x, then take a look at the Loki library, but with C++0x a type list is simple enough:
template <typename ... Args> type_list {}; // generic type list
typedef type_list< A, B, C, D > types; // our concrete list of types A, B, C and D
// this is the only source of duplication:
// types must be defined and added to the
// type_list manually [*]
Now we need to use some metaprogramming to operate on the type list, we can for example count the number of elements in the list:
template <typename List> struct size; // declare
template <typename T, typename ... Args> // general case (recursion)
struct size< type_list<T,Args...> > {
static const int value = 1 + size< type_list<Args...>::value;
};
template <> // stop condition for the recursion
struct size< type_list<> > {
static const int value = 0;
};
Having the size of the type list is a first step in our problem, as it allows us to define an array of functions:
typedef void (*function_t)(); // signature of each function pointer
struct registry {
static const int size = ::size< types >::value;
static const function_t table[ size ];
};
function_t registry::table[ registry::size ]; // define the array of pointers
Now we want to register the static functions from each particular type in that array, and for that we create an auxiliar function (encapsulated as a static function in a type to allow for partial specializations). Note that this concrete part is designed to be run during initialization: it will NOT be compile time, but the cost should be trivial (I would be more worried on the binary size with all the templates):
template <typename T, int N> // declaration
struct register_types_impl;
template <typename T, typename ... Args, int N> // general recursion case
struct register_types_impl< type_list<T,Args...>, N> {
static int apply() {
registry::table[ N ] = &T::f; // register function pointer
return register_types_impl< type_list<Args...>, N+1 >;
}
};
template <int N> // stop condition
struct register_types_impl< type_list<>, int N> {
static int apply() { return N; }
};
// and a nicer interface:
int register_types() {
register_types_impl< types, 0 >();
}
Now we need an id function that maps our types to the function pointer, which in our case is the position of the type in the type list
template <typename T, typename List, int N> // same old, same old... declaration
struct id_impl;
template <typename T, typename U, typename ... Args, int N>
struct id_impl< T, type_list<U, Args...>, N > { // general recursion
static const int value = id_impl< T, type_list<Args...>, N+1 >;
};
template <typename T, typename ... Args, int N> // stop condition 1: type found
struct id_impl< T, type_list<T, Args...>, N> {
static const int value = N;
};
template <typename T, int N> // stop condition 2: type not found
struct id_impl< T, type_list<>, N> {
static const int value = -1;
}
// and a cleaner interface
template <typename T, typename List>
struct id {
static const int value = id_impl<T, List, 0>::value;
};
Now you just need to trigger the registration at runtime, before any other code:
int main() {
register_types(); // this will build the lookup table
}
[*] Well... sort of, you can use a macro trick to reuse the types, as the use of macros is limited, it will not be that hard to maintain/debug.
The compiler knows all f()s of all instantiated classes at compile-time.
There's your mistake. The compiler knows nothing about template instantiations in other compilation units. It should now be pretty obvious why the number of instantiations isn't a constant integral expression that could be used as a template argument (and what if std::array was specialized? Halting Problem ahead!)

Template metaprogram converting type to unique number

I just started playing with metaprogramming and I am working on different tasks just to explore the domain. One of these was to generate a unique integer and map it to type, like below:
int myInt = TypeInt<AClass>::value;
Where value should be a compile time constant, which in turn may be used further in meta programs.
I want to know if this is at all possible, and in that case how. Because although I have learned much about exploring this subject I still have failed to come up with an answer.
(P.S. A yes/no answer is much more gratifying than a c++ solution that doesn't use metaprogramming, as this is the domain that I am exploring)
In principle, this is possible, although the solution probably isn't what you're looking for.
In short, you need to provide an explicit mapping from the types to the integer values, with one entry for each possible type:
template< typename T >
struct type2int
{
// enum { result = 0 }; // do this if you want a fallback value
};
template<> struct type2int<AClass> { enum { result = 1 }; };
template<> struct type2int<BClass> { enum { result = 2 }; };
template<> struct type2int<CClass> { enum { result = 3 }; };
const int i = type2int<T>::result;
If you don't supply the fallback implementation in the base template, this will fail for unknown types if T, otherwise it would return the fallback value.
Depending on your context, there might be other possibilities, too. For example, you could define those numbers within within the types themselves:
class AClass {
public:
enum { inta_val = 1 };
// ...
};
class BClass {
public:
enum { inta_val = 2 };
// ...
};
// ...
template< typename T >
struct type2int
{
enum { result = T::int_val }; // will fail for types without int_val
};
If you give more context, there might be other solutions, too.
Edit:
Actually there isn't any more context to it. I was looking into if it actually was possible, but without assigning the numbers itself.
I think Mike's idea of ordering is a good way to do this (again, for a fixed set of types) without having to explicitly assign numbers: they're implicitly given by the ordering. However, I think that this would be easier by using a type list. The index of any type in the list would be its number. I think something like the following might do:
// basic type list manipulation stuff
template< typename T1, typename T2, typename T3...>
struct type_list;
// meta function, List is assumed to be some instance of type_list
template< typename T, class List >
struct index_of {
enum { result = /* find index of T in List */ };
};
// the list of types you support
typedef type_list<AClass, BClass, CClass> the_type_list;
// your meta function
template< typename T >
struct type2int
{
enum { result = index_of<T, the_type_list>::result };
};
This does what you want. Values are assigned on need. It takes advantage of the way statics in functions are assigned.
inline size_t next_value()
{
static size_t id = 0;
size_t result = id;
++id;
return result;
}
/** Returns a small value which identifies the type.
Multiple calls with the same type return the same value. */
template <typename T>
size_t get_unique_int()
{
static size_t id = next_value();
return id;
}
It's not template metaprogramming on steroids but I count that as a good thing (believe me!)
Similiar to Michael Anderson's approach but this implementation is fully standards compliant and can be performed at compile time. Beginning with C++17 it looks like constexpr values will be allowed to be used as a template parameter for other template meta programming purposes. Also unique_id_type can be compared with ==, !=, >, <, etc. for sorting purposes.
// the type used to uniquely identify a list of template types
typedef void (*unique_id_type)();
// each instantiation of this template has its own static dummy function. The
// address of this function is used to uniquely identify the list of types
template <typename... Arguments>
struct IdGen {
static constexpr inline unique_id_type get_unique_id()
{
return &IdGen::dummy;
}
private:
static void dummy(){};
};
The closest I've come so far is being able to keep a list of types while tracking the distance back to the base (giving a unique value). Note the "position" here will be unique to your type if you track things correctly (see the main for the example)
template <class Prev, class This>
class TypeList
{
public:
enum
{
position = (Prev::position) + 1,
};
};
template <>
class TypeList<void, void>
{
public:
enum
{
position = 0,
};
};
#include <iostream>
int main()
{
typedef TypeList< void, void> base; // base
typedef TypeList< base, double> t2; // position is unique id for double
typedef TypeList< t2, char > t3; // position is unique id for char
std::cout << "T1 Posn: " << base::position << std::endl;
std::cout << "T2 Posn: " << t2::position << std::endl;
std::cout << "T3 Posn: " << t3::position << std::endl;
}
This works, but naturally I'd like to not have to specify a "prev" type somehow. Preferably figuring out a way to track this automatically. Maybe I'll play with it some more to see if it's possible. Definitely an interesting/fun puzzle.
I think it is possible to do it for a fixed set of types, but quite a bit of work. You'll need to define a specialisation for each type, but it should be possible to use compile-time asserts to check for uniqueness. I'll assume a STATIC_ASSERT(const_expr), like the one in Boost.StaticAssert, that causes a compilation failure if the expression is false.
Suppose we have a set of types that we want unique IDs for - just 3 for this example:
class TypeA;
class TypeB;
typedef int TypeC;
We'll want a way to compare types:
template <typename T, typename U> struct SameType
{
const bool value = false;
};
template <typename T> struct SameType<T,T>
{
const bool value = true;
};
Now, we define an ordering of all the types we want to enumerate:
template <typename T> struct Ordering {};
template <> struct Ordering<void>
{
typedef TypeC prev;
typedef TypeA next;
};
template <> struct Ordering<TypeA>
{
typedef void prev;
typedef TypeB next;
};
template <> struct Ordering<TypeB>
{
typedef TypeA prev;
typedef TypeC next;
};
template <> struct Ordering<TypeC>
{
typedef TypeB prev;
typedef void next;
};
Now we can define the unique ID:
template <typename T> struct TypeInt
{
STATIC_ASSERT(SameType<Ordering<T>::prev::next, T>::value);
static int value = TypeInt<T>::prev::value + 1;
};
template <> struct TypeInt<void>
{
static int value = 0;
};
NOTE: I haven't tried compiling any of this. It may need typename adding in a few places, and it may not work at all.
You can't hope to map all possible types to an integer field, because there are an unbounded number of them: pointer types with arbitrary levels of indirection, array types of arbitrary size and rank, function types with arbitrary numbers of arguments, and so on.
I'm not aware of a way to map a compile-time constant integer to a type, but I can give you the next best thing. This example demonstrates a way to generate a unique identifier for a type which - while it is not an integral constant expression - will generally be evaluated at compile time. It's also potentially useful if you need a mapping between a type and a unique non-type template argument.
struct Dummy
{
};
template<typename>
struct TypeDummy
{
static const Dummy value;
};
template<typename T>
const Dummy TypeDummy<T>::value = Dummy();
typedef const Dummy* TypeId;
template<typename T, TypeId p = &TypeDummy<T>::value>
struct TypePtr
{
static const TypeId value;
};
template<typename T, TypeId p>
const TypeId TypePtr<T, p>::value = p;
struct A{};
struct B{};
const TypeId typeA = TypePtr<A>::value;
const TypeId typeB = TypePtr<B>::value;
I developed this as a workaround for performance issues with ordering types using typeid(A) == typeid(B), which a certain compiler fails to evaluate at compile time. It's also useful to be able to store TypeId values for comparison at runtime: e.g. someType == TypePtr<A>::value
This may be doing some "bad things" and probably violates the standard in some subtle ways... but thought I'd share anyway .. maybe some one else can sanitise it into something 100% legal? But it seems to work on my compiler.
The logic is this .. construct a static member function for each type you're interested in and take its address. Then convert that address to an int. The bits that are a bit suspect are : 1) the function ptr to int conversion. and 2) I'm not sure the standard guarantees that the addresses of the static member functions will all correctly merge for uses in different compilation units.
typedef void(*fnptr)(void);
union converter
{
fnptr f;
int i;
};
template<typename T>
struct TypeInt
{
static void dummy() {}
static int value() { converter c; c.f = dummy; return c.i; }
};
int main()
{
std::cout<< TypeInt<int>::value() << std::endl;
std::cout<< TypeInt<unsigned int>::value() << std::endl;
std::cout<< TypeInt< TypeVoidP<int> >::value() << std::endl;
}
I don't think it's possible without assigning the numbers yourself or having a single file know about all the types. And even then you will run into trouble with template classes. Do you have to assign the number for each possible instantiation of the class?
type2int as compile time constant is impossible even in C++11. Maybe some rich guy should promise a reward for the anwser? Until then I'm using the following solution, which is basically equal to Matthew Herrmann's:
class type2intbase {
template <typename T>
friend struct type2int;
static const int next() {
static int id = 0; return id++;
}
};
template <typename T>
struct type2int {
static const int value() {
static const int id = type2intbase::next(); return id;
}
};
Note also
template <typename T>
struct type2ptr {
static const void* const value() {
return typeid(T).name();
}
};