Integer range based template specialisation [duplicate] - c++

This question already has answers here:
How can I specialize a C++ template for a range of integer values?
(4 answers)
Closed 5 years ago.
I was trying to get a specialisation based on integer value as the template type. If I use a single integer, specialisation is straight forward. Is it possible to have a simple template specialisation based on range without using boost foundation.
This is representative code translates to
template <typename int val>
class Param
{
public:
};
template <> class Param<0 to 100>
{
};
template <> class Param<100 to 175>
{
};

Here is one (simple) way to implement your requirements using SFINAE:
template<bool> struct Range;
template<int val, typename = Range<true> >
class Param
{};
template<int val>
class Param<val, Range<(0 <= val && val <= 100)> >
{};
template<int val>
class Param<val, Range<(100 < val && val <= 175)> >
{};
Demo.

You can use SFINAE with std::enable_if to make your own handy compile-time range testing class:
#include <iostream>
#include <type_traits>
using namespace std;
template<int Start, int End, int Val, class Enable = void>
struct crange { };
template<int Start, int End, int Val>
struct crange<Start, End, Val, typename std::enable_if<Val >= Start && Val <= End>::type> {
typedef void enabled;
};
template<int Val, class Enable = void>
class Param {
public:
Param() : value(422) { }
int value;
};
template<int Val> // V VV the range [x, y]
class Param<Val, typename crange<0, 10, Val>::enabled> {
public:
Param() : value(1.32) { }
double value;
};
int main() {
Param<1> pdouble;
Param<50> pint;
cout << pdouble.value << endl; // prints 1.32
cout << pint.value << endl; // prints 422
}

Is it possible to have a simple template specialisation based on range without using boost foundation.
Not for C++03 in a really elegant, concise, maintainable and generic way where arbitarily large ranges can be easily specified. To keep the code concise, you'd need something like the boost preprocessor library to loop over a range of values.
Sans BOOST or reimplementing huge chunks of it, you could create some sad little macros to call the initial macro for a specific number of consecutive values. For example:
#define X(N) template <> class Param<N> { ... };
#define X2(N) X(N) X(N+1)
#define X4(N) X2(N) X2(N+2)
#define X8(N) X4(N) X4(N+4)
...
// template <> class Param<100 to 175> then becomes
X64(100); // 100..163
X8(164); // 164..171
X4(172); // 172..175
Alternatively, you could use a program/script to write your C++ code, as an earlier compilation step, sometimes that works out better - sometimes worse - than preprocessor hackery.

Related

Insert a transformed integer_sequence into a variadic template argument?

How do you insert a transformed integer_sequence (or similar since I am targeting C++11) into a variadic template argument?
For example I have a class that represents a set of bit-wise flags (shown below). It is made using a nested-class because you cannot have two variadic template arguments for the same class. It would be used like typedef Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::WithValues<0x01, 0x02, 0x04> MyFlags. Typically, they will be used with the values that are powers of two (although not always, in some cases certain combinations would be made, for example one could imagine a set of flags like Read=0x1, Write=0x2, and ReadWrite=0x3=0x1|0x2). I would like to provide a way to do typedef Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::WithDefaultValues MyFlags.
template<class _B, template <class,class,_B> class... _Fs>
class Flags
{
public:
template<_B... _Vs>
class WithValues :
public _Fs<_B, Flags<_B,_Fs...>::WithValues<_Vs...>, _Vs>...
{
// ...
};
};
I have tried the following without success (placed inside the Flags class, outside the WithValues class):
private:
struct _F {
// dummy class which can be given to a flag-name template
template <_B _V> inline constexpr
explicit _F(std::integral_constant<_B, _V>) { } };
// we count the flags, but only in a dummy way
static constexpr unsigned _count = sizeof...(_Fs<_B, _F, 1>);
static inline constexpr
_B pow2(unsigned exp, _B base = 2, _B result = 1) {
return exp < 1 ?
result :
pow2(exp/2,
base*base,
(exp % 2) ? result*base : result);
}
template <_B... _Is> struct indices {
using next = indices<_Is..., sizeof...(_Is)>;
using WithPow2Values = WithValues<pow2(_Is)...>;
};
template <unsigned N> struct build_indices {
using type = typename build_indices<N-1>::type::next;
};
template <> struct build_indices<0> {
using type = indices<>;
};
//// Another attempt
//template < _B... _Is> struct indices {
// using WithPow2Values = WithValues<pow2(_Is)...>;
//};
//template <unsigned N, _B... _Is> struct build_indices
// : build_indices<N-1, N-1, _Is...> { };
//template < _B... _Is> struct build_indices<0, _Is...>
// : indices<_Is...> { };
public:
using WithDefaultValues =
typename build_indices<_count>::type::WithPow2Values;
Of course, I would be willing to have any other alternatives to the whole situation (supporting both flag names and values in the same template set, etc).
I have included a "working" example at ideone: http://ideone.com/NYtUrg - by "working" I mean compiles fine without using default values but fails with default values (there is a #define to switch between them).
Thanks!
So I figured it out on my own, I guess I posted too soon.
I was able to get around the error generated with the given code with a dummy template argument in the build_indices and indices template classes above. The argument has to be a typename as they currently have variadic integral types.
(Note: still using the improper _F names here - I have corrected my personal code to not use these reserved name - thanks for the tip)
Here is a working solution which results in the WithValues<...> template to be filled with powers of 2 (1, 2, 4, 8, 16, ...) based on the size of the Flags variadic template.
private:
// dummy class which can be given to a flag-name template
struct _F
{
template <_B _V> inline constexpr
explicit _F(std::integral_constant<_B, _V>) { }
};
// we count the flags, but only in a dummy way
static constexpr unsigned _count = sizeof...(_Fs<_B, _F, 1>);
static inline constexpr
_B pow2(unsigned exp, _B base = 2, _B result = 1)
{
return exp < 1 ?
result :
pow2(exp/2, base*base, (exp % 2) ? result*base : result);
}
template <class dummy, _B... _Is> struct indices
{
using next = indices<dummy, _Is..., sizeof...(_Is)>;
using WithPow2Values = WithValues<pow2(_Is)...>;
};
template <class dummy, unsigned N> struct build_indices
{
using type = typename build_indices<dummy, N-1>::type::next;
};
template <class dummy> struct build_indices<dummy, 0>
{
using type = indices<dummy>;
};
public:
using WithDefaultValues =
typename build_indices<void, _count>::type::WithPow2Values;

C++ Metaprogramming: Store integer by type

I want to store integers for given types which should be used during compilation and during runtime.
Up to now I have the following:
template<typename T>
struct my_int { enum { result = -1 }; };
And I specialize for each type:
template<> struct my_int<a_type> { enum { result = 5 }; };
And I can check during compile time (of course the check here would be against another compile time constant):
static_assert(my_int<a_type>::result == 5, "Bla");
Problem:
This works well, as long as the specialization is in the same namespace. But that is an inconvenience I want to get rid of. So I want to be able to use it in every namespace:
namespace foo {
template<> struct my_int<a_type> { enum { result = 5 }; };
}
namespace bar {
template<> struct my_int<b_type> { enum { result = 7 }; };
}
Any ideas how I could do this?
C++11 and boost is ok for my situation, if really needed.
Update: Seems I gave to little information. The types are mainly enum classes. If you're really interested you can see the real implementation here, http://www.codeduce.com/extra/enum_tools, download the zip and in the header line 33, 34.
For some reason I found the problem description easy to misunderstand, but the linked code makes it clear. In C++11 it's easy:
#define SETUP_ENUM_LENGTH(enum_type, length) \
static constexpr int enum_length(enum_type*) { return length; }
and a
for (int i = 0; i < enum_length((Enum*)0); ++i) {
in the right place. Here's a sample:
#include <iostream>
#include <functional>
#include <boost/preprocessor/variadic/size.hpp>
/**
* Macro to setup an enum completely.
* First parameter is the name, following are the states as plain text.
*/
#define DEF_ENUM(name, ...) \
enum class name : uint8_t { __VA_ARGS__ }; \
SETUP_ENUM_LENGTH(name, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__))
/**
* Once an enum class is defined, this macro makes the size publicly available.
* Needed by enum_array. Already included in DEF_ENUM.
*/
#define SETUP_ENUM_LENGTH(enum_type, length) \
static constexpr int enum_length(enum_type*) { return length; }
/**
* Function to iterate over all elements of an enum.
*/
template<typename Enum>
void enum_for_each(const std::function<void(Enum e)> &fct) {
for (int i = 0; i < enum_length((Enum*)0); ++i) {
fct(static_cast<Enum>(i));
}
}
namespace n {
DEF_ENUM(demo,u,v,w,x,y,z,a,b,c);
}
namespace m {
DEF_ENUM(demo,a=3,b=1,c=4,d=1,e=5);
}
using std::cout;
int main()
{
enum_for_each<n::demo>([](n::demo e) { cout<<int(e); });
cout<<'\n';
enum_for_each<m::demo>([](m::demo e) { cout<<int(e); });
cout<<'\n';
int ndemo[enum_length((n::demo*)0)];
int mdemo[enum_length((m::demo*)0)];
cout << sizeof ndemo << ' ' << sizeof mdemo << '\n';
}
As a side note, that static_cast<Enum>(i) looks troublesome, does it really do the right thing with the m::demo enum?
To preserve the original templated-enum_length usage and so make the array-allocation usage a bit prettier is easy from here, rename the function enum_length_helper and then
template<typename Enum>
struct enum_length {
enum result=enum_length_helper((Enum*)0);
};
If it is possible for your use-case, you could do specialization on a namespace basis and then aggregate as follows, using C++11 since you mentioned it but can work without.
Assume you have a number of namespaces ns_1 to ns_k like this:
namespace ns_i {
template<class T> struct my_int: std::integral_constant<int, -1> {};
/*...*/
enum e_1 { /*...*/ };
template<> struct my_int<e_1>: std::integral_constant<int, 101> {};
/*...*/
enum e_n { /*...*/ };
template<> struct my_int<e_n>: std::integral_constant<int, 142> {};
/*...*/
}
I assume you already have the means to do a unique numbering. Then you aggregate the my_int from all namespaces like this:
namespace your_lib {
template<
class T,
template<class> class sources... /* any number of template classes,
each taking one type argument */
>
struct Union:
std::integral_constant<int, -1> {}; // default -1 for (empty template list)
template<
class T,
template<class> class source, // match first template
template<class> class sources... // match all but first template
>
struct Union<T, source, sources...>:
std::conditional<
source::value == -1,
union<T, sources...>, // recursively call union on all but first tempalte
source // or if there's a value in first, use it
> {};
template<class T> struct my_int :
Union<T, ns_1::my_int, /*...,*/ ns_k::my_int> {};
/* here you could use boost preprocessor to iterate over the namespaces
since you mentionned it */
}
Here's a solution using functions and ADL:
#include <type_traits>
enum TypeInfo
{
Unknown = 0,
TypeA,
TypeB
};
template <TypeInfo x>
using TInfo = std::integral_constant<TypeInfo, x>;
template <class T>
TInfo<Unknown> TypeInfoFunc(T);
template <class T>
struct GetTypeInfo : decltype(TypeInfoFunc(std::declval<T>())){};
namespace a{
class A{};
TInfo<TypeA> TypeInfoFunc(A);
};
namespace b {
class B{};
TInfo<TypeB> TypeInfoFunc(B);
}
int main()
{
static_assert(GetTypeInfo<a::A>::value == TypeA, "");
static_assert(GetTypeInfo<b::B>::value == TypeB, "");
return 0;
}
The TypeInfoFunc is found using ADL meaning that it can be defined in the same namespace as the class your specializing it for.
EDIT
Based on the comments, I think I understand a bit better now. The solution doesn't change much, simply make your function:
namespace a
{
struct A{};//Or whatever class you want to hold data about your type
A TypeInfoFunc(TInfo<TypeA>);
}
and change GetTypeInfo to
template <TypeInfo x>
struct GetTypeInfo : decltype(TypeInfoFunc(TypeInfo<X>())) {};
This way you can call GetTypeInfo<TypeA> and access all the information in (in this case) class A.
you can avoid the need to specialize a structure if you move the type information in the type itself:
template <int V>
struct TypeInfo { enum { result = V, }; };
class yourClass : TypeInfo<2> //works better if you have an enum instad of number
{}
//...
static_assert(a_type::result == 2);
If you do this you will never have the problem with namespaces if the type is declared you will always have access to type info.

C++ metaprogramming

I have the following problem:
Suppose I have some basic counter class Counter. And suppose we also have some sets of classes, that can be counted. Let's name some of them class CountedA and class CountedB.
Now, every class, which can be counted (such as CountedA and CountedB) has the following statically declared parts: one enum and one int part, that acts like a part of counted data.
For example, it's declaration could look the following way:
enum CountedType { A, B };
template <CountedType Type, int N>
class Counted { };
// Now we can declare 'CountedA' and 'CountedB'
typedef Counted<A, 25> CountedA;
typedef Counted<B, 7> CountedB;
Now, the declaration of the counter:
// C++0x variadic or simply bunch of 'typename XX' definitions for C++03
template <typename T0, typename T1, typename ...>
class Counter
{
// I don't know how to implement this
// for now!
int GetTotalN() { ... }
// Retrieve the corresponding type
// so that GetTypeAt<0> returns
// enum from 'T0'
template <int Pos>
CountedType GetTypeAt() { ... }
};
I want to be able to write something like:
class RealCounter : public Counter<CountedA, CountedB> { };
And use it the following way:
RealCounter counter;
int n = counter.GetTotalN();
CountedType type = counter.GetTypeAt<0>();
Now, I'm pretty sure that this can be done. But what's the best way of implementing it? (don't ask me why would I need such crazy kind of things :)
Does boost::mpl offer something for this case?
Thank you.
Small update:
In this particular example, GetTotalN() should return 25 + 7.
If we add, for example, typedef Counted<C, 2> CountedC, then the result for
RealCounter : public Counter<CountedA, CountedB, CountedC>
should become 25 + 7 + 2.
Here's C++03 code which works (for up to 10 template arguments). The main trick is giving class Counter a multiple inheritance, and passing objects of type Counter to function templates which must select a base class. The actual summation is done recursively.
Counter.hpp
enum CountedType { A, B };
template <CountedType Type, int N>
struct Counted {};
struct DummyCounted {};
template <int Pos, typename T>
struct IndexedType {};
template <unsigned int Terms>
struct PartialSum
{
template <typename CounterT>
static int getSum(const CounterT& ctr)
{ return PartialSum<Terms-1>::getSum(ctr) + ctr.template GetNAt<Terms>(); }
};
template <> struct PartialSum<0U>
{
template <typename CounterT>
static int getSum(const CounterT& ctr)
{ return ctr.template GetNAt<0>(); }
};
template <typename T0, typename T1=DummyCounted,
typename T2=DummyCounted, typename T3=DummyCounted,
typename T4=DummyCounted, typename T5=DummyCounted,
typename T6=DummyCounted, typename T7=DummyCounted,
typename T8=DummyCounted, typename T9=DummyCounted>
class Counter :
public IndexedType<0, T0>, public IndexedType<1, T1>,
public IndexedType<2, T2>, public IndexedType<3, T3>,
public IndexedType<4, T4>, public IndexedType<5, T5>,
public IndexedType<6, T6>, public IndexedType<7, T7>,
public IndexedType<8, T8>, public IndexedType<9, T9>
{
public:
static int GetTotalN() {
return PartialSum<9>().getSum( Counter() );
}
template <int Pos>
static CountedType GetTypeAt() { return _getTypeAt<Pos>( Counter() ); }
template <int Pos>
static int GetNAt() { return _getNAt<Pos>( Counter() ); }
private:
template <int Pos, CountedType Type, int N>
static CountedType _getTypeAt(const IndexedType<Pos, Counted<Type,N> >&)
{ return Type; }
template <int Pos, CountedType Type, int N>
static int _getNAt(const IndexedType<Pos, Counted<Type,N> >&)
{ return N; }
template <int Pos>
static int _getNAt(const IndexedType<Pos, DummyCounted>&)
{ return 0; }
};
Counter.cpp
#include "Counter.hpp"
#include <iostream>
typedef Counted<A, 25> CountedA;
typedef Counted<B, 7> CountedB;
class RealCounter : public Counter<CountedA, CountedB> {};
int main()
{
RealCounter counter;
int n = counter.GetTotalN();
CountedType type = counter.GetTypeAt<0>();
std::cout << "n is " << n
<< "\ntype check is " << (type == A) << std::endl;
return 0;
}
Output:
n is 32
type check is 1
That C++0x variadic template stuff looks interesting, but I haven't taken a good look at it yet. But I do think in C++0x, all this example's functions (except main of course) could be constexpr.
I'm not sure why you need to embed those parameters in the templates arguments and not simply in a constructor since they are all the same types for each "derived" CountedA/B types.
Anyways you can embed the resulting types into a std::tuple as shown in the link below (see Message class for an example). Then create a variadic template function similar to the applyTuple version in the link below that will add all your integer arguments and return the final result once all arguments have been unrolled. As for the returning of the enum value for the item in "Pos" simply call the get( tuple ).getEnum() or .value to get it.
How do I expand a tuple into variadic template function's arguments?

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();
}
};

C++ metaprogramming - generating errors in code

Is there a way that I can create a function that takes an int template parameter, and have that function give a compile time error if the value passed to the function is less than 10?
The following code does not work, but it shows what I want to accomplish:
template <int number1>
void reportErrorIfLessThan10()
{
#if(number1 < 10)
#error the number is less than 10
#endif
}
int maint(int argc, char**argv)
{
reportErrorIfLessThan10<5>();//report an error!
reportErrorIfLessThan10<12>();//ok
return 0;
}
If you don't want Boost C++ Libraries magic and want bare bones...
template<bool> class static_check
{
};
template<> class static_check<false>
{
private: static_check();
};
#define StaticAssert(test) static_check<(test) != 0>()
Then use StaticAssert. It's a #define for me because I have code that needs to run in a lot of environments where C++ doesn't work right for templates and I need to just back it off to a runtime assert. :(
Also, not the best error messages.
If for some reason you can't use Boost, this example is trivially written like this:
template <int number1>
void reportErrorIfLessThan10()
{
typedef char number1_gt_10[number1 > 10 ? 1 : -1];
}
int maint(int argc, char**argv)
{
reportErrorIfLessThan10<5>();//report an error!
reportErrorIfLessThan10<12>();//ok
return 0;
}
Or more generic
#define static_assert(test, message) typedef char static_assert_at_ ## __LINE__[(test) ? 1 : -1];
I'm not concatenating the error message itself, because I feel that static_assert(true, "some message"); is more readable than say static_assert(true, some_message);. However, this does limit the use case to only one assert per line.
template <int number1>
typename boost::enable_if_c< (number1 >= 10) >::type
reportErrorIfLessThan10() {
// ...
}
The above enable_if, without the _c because we have a plain bool, looks like this:
template<bool C, typename T = void>
struct enable_if {
typedef T type;
};
template<typename T>
struct enable_if<false, T> { };
Boost's enable_if takes not a plain bool, so they have another version which has a _c appended, that takes plain bools. You won't be able to call it for number1 < 10. SFINAE will exclude that template as possible candidates, because enable_if will not expose a type ::type if the condition evaluates to false. If you want, for some reason, test it in the function, then if you have the C++1x feature available, you can use static_assert:
template <int number1>
void reportErrorIfLessThan10() {
static_assert(number >= 10, "number must be >= 10");
}
If not, you can use BOOST_STATIC_ASSERT:
template <int number1>
void reportErrorIfLessThan10() {
BOOST_STATIC_ASSERT(number >= 10);
}
The only way to display a descriptive message is using static_assert, though. You can more or less simulate that, using types having names that describe the error condition:
namespace detail {
/* chooses type A if cond == true, chooses type B if cond == false */
template <bool cond, typename A, typename B>
struct Condition {
typedef A type;
};
template <typename A, typename B>
struct Condition<false, A, B> {
typedef B type;
};
struct number1_greater_than_10;
}
template <int number1>
void reportErrorIfLessThan10() {
// number1 must be greater than 10
sizeof( typename detail::Condition< (number1 >= 10),
char,
detail::number1_greater_than_10
>::type );
}
It prints this here:
error: invalid application of 'sizeof' to incomplete type 'detail::number1_greater_than_10'
But I think the very first approach, using enable_if will do it. You will get an error message about an undeclared reportErrorIfLessThan10.
litb and Joe have already given the answers used in practice. Just to illustrate how this can be done manually by specializing for the number in question (rather than a general boolean condition):
template <int N>
struct helper : helper<N - 1> { };
template <>
struct helper<10> { typedef void type; };
template <>
struct helper<0> { }; // Notice: missing typedef.
template <int N>
typename helper<N>::type error_if_less_than_10() {
}
int main() {
error_if_less_than_10<10>();
error_if_less_than_10<9>();
}
Functions cannot be inherited but classes (and structs) can. Therefore, this code also uses a struct that automatically and dynamically generates cases for all N except 10 and 0, which are the hard-coded recursion begins.
By the way, the above code actually gives quite nice error messages:
x.cpp:16: error: no matching function for call to 'error_if_less_than_10()'