Sorry for confused title. I don't know how else to say it. Example should explain itself.
I found something called typemaps and use it to my code like this:
template<typename T>
struct typemap
{
static const int INDEX;
};
template<>
const int typemap<Type1>::INDEX = 1;
template<>
const int typemap<Type2>::INDEX = 3;
template<>
const int typemap<Type3>::INDEX = 11;
Type1 Type2 & Type3 are stucts and used like type in here. The INDEX number cannot be inside the struct because there could be another typemap with different numbers but with the same type-object. So the typemap works for different order of the stucts in colection like vector, because the order matter to me.
Next thing is non-template class which has Type1-3 as attributes. And what I'm trying to do is to insert these attributes into vector, that is done with help of std::function. But I need to take general typemap and use it as index to insert to vector.
The only thing i thought it may work is using more templates. Something like the next code, but this is not correct way and since I'm still new to templates I need help to write it correctly so the body of function toVector
start working as i need.
class MyClass
{
Type1 type1_;
Type2 type2_;
Type3 type3_;
..
template<typename T>
void toVector(T& typemap)
{
std::vector<..> vect;
vect.resize(..);
vect[typemap<Type1>::INDEX] = type1_.someFunction(..);
vect[typemap<Type2>::INDEX] = type2_.someFunction(..);
}
};
I'm sure i use the template wrong with the member function, i somehow need to say that T parameter also have some template parameter. Sorry for my english, not native speaker. Also sorry for the ".." It's unrelated to my problem and it would mess the code.
Barry's answer is a better way to do what you are trying to do, but here is the answer to your specific question regarding having a template parameter that is itself a template taking one parameter:
template<template<typename> class type_with_one_template_parameter>
void toVector()
{
std::vector<..> vect;
vect.resize(..);
vect[type_with_one_template_parameter<Type1>::INDEX] = type1_.someFunction(..);
vect[type_with_one_template_parameter<Type2>::INDEX] = type2_.someFunction(..);
}
It wasn't clear why the function had the T& typemap parameter in your original example, so I've removed it.
Instead of adding explicit specializations for INDEX, let's create an actual object type typemap which you can pass around. First some boilerplate:
template <class T>
struct tag_type {
using type = T;
};
template <class T>
constexpr tag_type<T> tag{};
template <int I>
using int_ = std::integral_constant<int, I>;
Now, we create an object with a bunch of overloads for index() which take different tag_types and return different int_s.:
struct typemap {
constexpr int_<3> size() const { return {}; }
constexpr int_<1> index(tag_type<Type1> ) const { return {}; }
constexpr int_<3> index(tag_type<Type2> ) const { return {}; }
constexpr int_<11> index(tag_type<Type3> ) const { return {}; }
};
which is something that you can pass in to a function template and just use:
template<typename T>
??? toVector(T const& typemap)
{
std::vector<..> vect;
vect.resize(typemap.size());
vect[typemap.index(tag<Type1>)] = ...;
vect[typemap.index(tag<Type2>)] = ...;
vect[typemap.index(tag<Type3>)] = ...;
}
I would like to have an array which has a length that depends on the parameter of my template, but I keep getting the "expected constant expression" error.
enum MyEnum
{
FIRST,
OTHER
};
template<MyEnum e>
struct MyTemplate
{
static const int arrSize;
int myArr[arrSize]; // error C2057: expected constant expression
// int myArr[e == FIRST ? 4 : 10]; // works, but isn't very readable...
};
template<>
const int MyTemplate<FIRST>::arrSize = 4;
template<>
const int MyTemplate<OTHER>::arrSize = 10;
The compiler I must use does not support constexpr, or any other C++ 11 features, and I also cannot pass the array size as a template parameter.
edit: I also must not use new.
Thanks
In some cases like this, I'll add a function get_array_size<e>(). Since you say you don't have constexpr, there's still decent possibilities:
//I call this a pseudo-template-function, but there's probably better names
template<MyEnum> struct GetArraySize; //compiler error for default
template<> struct GetArraySize<FIRST> {static const int value=4;};
template<> struct GetArraySize<OTHER> {static const int value=10;};
template<MyEnum e>
struct MyTemplate
{
static const int arrSize = GetArraySize<e>::value;
int myArr[arrSize];
};
http://coliru.stacked-crooked.com/a/f03a5fa94a038892
Are we reinventing the wheel here ? Enums are compile time constants. Just do this :
enum MyEnum
{
FIRST = 4,
OTHER = 10
};
template<MyEnum e>
struct MyTemplate
{
int myArr[e];
};
demo
Quick question (Theory really). I have a variable that its type alternates depending on a value, for example:
8, 16, 24, 32
And I define this by doing, for example:
uint8_t = 10; // example
But, at the minute I'm switching the "number" and repeating the code but declaring the integer value differently. Which, as you can tell, is a lot of wasteful code and I want to code more effectively.
I'm wondering if It's possible to have template that assigns the variable depending on the value? (If that makes sense)..
if value == 8
uint8_t = foo;
elseif value == 16
uint32_t
...
Any ideas or suggestions? Thank you :)
Like so:
template <unsigned int N> struct IntN;
template <> struct IntN< 8> { typedef uint8_t type; };
template <> struct IntN<16> { typedef uint16_t type; };
template <> struct IntN<32> { typedef uint32_t type; };
template <> struct IntN<64> { typedef uint64_t type; };
IntN<8>::type x = 5;
The template argument has to be a constant expression.
Atm i have sth like that:
template<int n>
struct Pow
{
enum{val= Pow<n-1>::val<<1};
};
template<>
struct Pow<0>{
enum{val =1};
};
I can acess data like Pow<30>::val. It's good but i want do like this
int main()
{
Pow<30>::val;
and then use variable to
access all of value <0,30>
I knew that i can use array and dynamic programming but can i do that in this way?
Sorry for English.
Using C++0x variadic templates:
template<int... Indices>
struct powers {
static const int value[sizeof...(Indices)];
typedef powers<Indices..., sizeof...(Indices)> next;
};
template<int... Indices>
const int powers<Indices...>::value[sizeof...(Indices)] = { Pow<Indices>::val... };
template<int N>
struct build_powers {
typedef typename build_powers<N - 1>::type::next type;
};
template<>
struct build_powers<1> {
typedef powers<0> type;
};
and then:
int
main()
{
// we want [0..30] inclusive so pass 31 as exclusive upper limit
typedef build_powers<31>::type power_type;
// 0..30 is 31 powers in all
typedef const int array_type[31];
array_type& ref = power_type::value;
// ref[0] .. ref[30] are the values of Pow<0>::val .. Pow<30>::val
}
So that's with using an array but without dynamic initialization. Since you want the result as a variable and not for TMP I feel this is adequate.
When you do Pow<30>::val; you will instantiate the top of your two templates, then when it get's to zero it will instantiate the specialization, and only the final result will be visible at runtime, since templates are resolved at compile time
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();
}
};