Reputation: 101
I have this code, which works... so far so good :
struct _TYPEIDSTR {};
typedef _TYPEIDSTR *TYPE_ID;
template<class T> _TYPEIDSTR _TYPE_ID;
template<class T> constexpr TYPE_ID getTypeID() { return &_TYPE_ID<T>; }
calling in main like this :
constexpr TYPE_ID id1 = getTypeID<int>();
constexpr TYPE_ID id2 = getTypeID<int>();
RLOG("ID1 : " << id1);
RLOG("ID2 : " << id2);
works perfectly, and I've an unique identifier for each type used in getTypeID() call. Now I want to build a struct that brings some info about a function :
template<typename RES, typename... ARGS> struct _GlobalOverlayInfo {
bool _member;
RES(*_fn)(ARGS...);
size_t _nargs;
TYPE_ID _argIDs;
constexpr _GlobalOverlayInfo(RES(*fn)(ARGS...)) :
_member(false),
_fn(fn),
_nargs(sizeof...(ARGS)),
_argIDs {getTypeID<ARGS>()...}
{}
};
template<typename RES, typename... ARGS>
constexpr auto getOverlayInfo(RES(*fn)(ARGS...)) {
return & _GlobalOverlayInfo<RES, ARGS...>(fn); <<---ERROR1
}
using this function :
int pippo(int x) {
return 0;
}
and calling like this :
constexpr auto x = getOverlayInfo(pippo); <<--- ERROR2
I get the 2 marked errors; ERROR1 is "taking address of a temporary" (but shouldn't it a compile time evaluation ?) and ERROR2 is "error: ‘&’ is not a constant expression". I tried in many ways, but I couldn't success. Where I am wrong ? Is there a way (in C++11) to achieve this result ? All I need is a pointer to an unique structure generated for each RES and ARGS... parameters.
Upvotes: 0
Views: 854
Reputation: 66230
Not sure to understand what you want to do.
Anyway, if you want to works with C++11 (and avoid C++14 or newer) you can't use a template variable like
template<class T> _TYPEIDSTR _TYPE_ID;
that is a C++14 feature.
If you want a constexpr
template identifier, you could use std::type_index
, that is available starting from C++11.
If you can't use std::type_index
... well, the best I can imagine is a template class with a static
variable and a static
method that return the pointer to it.
Something like
template <typename>
struct typeId
{
static constexpr int const val {};
static constexpr int const * getId ()
{ return &val; }
};
template <typename T>
constexpr int const typeId<T>::val;
You can get constexpr
values and you can check that are differents
constexpr auto const idInt = typeId<int>::getId();
constexpr auto const idLong = typeId<long>::getId();
std::cout << (idInt != idLong) << std::endl; // print 1
For the function case...
Functions has types and single functions can be template parameters.
So if you want a constexpr
identifier for a function, you can create a wrapper as follows
template <typename Ft, Ft f>
struct funcT
{ };
and, using the preceding typeId
, get different constexpr
values from different functions as follows
int foo (int) { return 0; }
int bar (int) { return 0; }
long baz (int, long, long long) { return 0L; }
// ...
constexpr auto idFoo = typeId<funcT<decltype(&foo), &foo>>::getId();
constexpr auto idBar = typeId<funcT<decltype(&bar), &bar>>::getId();
constexpr auto idBaz = typeId<funcT<decltype(&baz), &baz>>::getId();
std::cout << (idFoo != idBar) << std::endl; // print 1
std::cout << (idFoo != idBaz) << std::endl; // print 1
Upvotes: 1