i am trying to implement a generic queue fifo, but i cannot make any progress in trying to select the correct specialization class from the one defined as a base template class.
Here is the code:
This code described first, a linked list implementation , so the class Node and the a enum class is defined to described the types of queue that is going to be used (linked list or fixed array), the first part (Node and GenericQueueType) work well, in the main function is defined first to do some test.
Then the wrapper function that going to be used as a wrapper class is not selecting the partial specialization defined for use the linked list.
#include <iostream>
#include <string>
//The node definition used for the linked list
template<typename ValueType>
struct Node_
{
Node_(): NodePtr(nullptr)
{}
Node_(const ValueType & aValue): _Value( aValue )
,NodePtr(nullptr)
{
}
ValueType _Value;
Node_ * NodePtr;
};
//====================
enum class EQueueType
{
EQueueType_Linked_List,
EQueueType_Fixed_Queue
};
//====================
template<EQueueType,class ... TypeValue>
struct GenericQueueType
{
};
template<class TypeValue>
struct GenericQueueType<EQueueType::EQueueType_Linked_List, TypeValue>
{
GenericQueueType():TopPtr(nullptr)
,BackPtr(nullptr)
{}
void insertValueInQueue(const TypeValue & aValue)
{
Node_<TypeValue > * aPtr=BackPtr;
BackPtr=new Node_<TypeValue>(aValue );
if(TopPtr==nullptr)
{
TopPtr=BackPtr;
}
else
{
BackPtr->NodePtr=aPtr;
}
}
void getValueFromQueue(TypeValue & aValue)
{
//aErrorcode=ERROR_PROCESS;
if (TopPtr!=nullptr)
{
Node_<TypeValue > * aPtr= TopPtr;
aValue=aPtr->_Value;
aPtr->_Value ;
TopPtr=TopPtr->NodePtr;
delete TopPtr;
TopPtr=nullptr;
}
}
private:
static const int ERROR_PROCESS = -1;
static const int OK_ERROR_CODE = 0;
Node_ <TypeValue > * TopPtr;
Node_ <TypeValue > * BackPtr;
};
//base queue wrapper
template<typename QueueType, typename ... Element>
class QueueFIFO
{
};
template< template<typename ... > class QueueType,typename EQ_type,typename ... TypeElement >
class QueueFIFO<QueueType<EQ_type,TypeElement ...>,EQ_type,TypeElement ... >
{
using value_type = typename std::tuple<TypeElement...>;
static const int INITIAL_SIZE=0;
public:
QueueFIFO():_Size(INITIAL_SIZE)
{}
void enqueue(const value_type & aElement)
{
Queue.insertValueInQueue(aElement);
}
void dequeue( value_type & aElement)
{
Queue.getValueFromQueue(aElement);
}
int size(){}
private:
int _Size;
QueueType<EQ_type,TypeElement ...> Queue;
};
int main()
{
float aElement=14;
GenericQueueType<EQueueType::EQueueType_Linked_List,float> aLinkedList;
aLinkedList.insertValueInQueue(aElement);
QueueFIFO<GenericQueueType<EQueueType::EQueueType_Linked_List,float>,float> _Queue;
_Queue.enqueue(aElement);
return 0;
}
Here is the compiler outs:
error: 'class QueueFIFO<GenericQueueType<(EQueueType)0, float>, float>' has no member named 'enqueue'
_Queue.enqueue(aElement);
^
I have been reading this from the standart:
In a type name that refers to a class template specialization, (e.g.,
A) the argument list shall match the template parameter
list of the primary template. The template arguments of a
specialization are deduced from the arguments of the primary template.
14.5.5.1
But still i cannot see the error.
Thx in advance!
The problem is somewhere in the template-template argument not actually creating a specialization. This is more clear if you declare the non-specialized version with just a ; instead of an empty definition.
The short answer is to not use template-template arguments; your code as written does not require them (or, in fact, any specialization at all of that template), and it is unlikely that you will ever see a case that needs them (in this case, it actually harms by eliminating possibly useful cases).
enqueue defined in your partial specialization of QueueFIFO takes a const & value_type where value_type is std::tuple. You are trying to call it with aElement which is a float, while you should be passing it a std::tuple<float>. Try passing std::make_tuple(aElement) to enqueue.
Also, as T.C. pointed out in the comments, the places you are using typename EQ_type and passing in an enum value of type EQueueType are erroneous - an enum value will not match a template type argument. You will have to use non-type arguments for that, as you have done in the definition of GenericQueueType.
Related
I give up, please help explain this behaviour. The example I present below is the simplest one I could think of, but it sums up the problem (using g++ 4.9.2 on Cygwin with c++14 enabled). I want to create a class which will behave similar to std::mem_fn. Here is my class:
template <class R, class T, R(T::*P)() const >
struct property {
static R get(const T& t) {
return (t.*P)();
}
};
where R is the return type and T is the type of the object I am interesting in. The third template parameter is a pointer to member function. So far, so good.
I then create a simple class which holds an integer as follows
class data_class {
public:
unsigned get_data() const {
return m_data;
}
private:
unsigned m_data;
};
This is the class which will be used in the property class shown before.
Now I create two classes which inherit from data_class as follows
struct my_classA
: public data_class {
using data = property<unsigned, data_class, &data_class::get_data>;
};
//same as my_classA, only templated
template <int I>
struct my_classB
: public data_class {
using data = property<unsigned, data_class, &data_class::get_data>;
};
They have the exact same inner typedef, but my_classB is templated. Now the following types should in theory be the same:
using target_t = property<unsigned, data_class, &data_class::get_data>;
using test1_t = typename my_classA::data;
using test2_t = typename my_classB<1>::data;
However my compiler says that only test1_t and target_t are the same. The type deduced for test2_t is apparently
property<unsigned int, data_class, (& data_class::get_data)> >
where this type has these brackets around the pointer to member function. Why test2_t is not the same as target_t? Here is the full code in case you want to try it on your system. Any help is much appreciated.
#include <type_traits>
class data_class {
public:
unsigned get_data() const {
return m_data;
}
private:
unsigned m_data;
};
//takes return type, class type, and a pointer to member function
//the get function takes an object as argument and uses the above pointer to call the member function
template <class R, class T, R(T::*P)() const >
struct property {
static R get(const T& t) {
return (t.*P)();
}
};
struct my_classA
: public data_class {
using data = property<unsigned, data_class, &data_class::get_data>;
};
//same as my_classA, only templated
template <int I>
struct my_classB
: public data_class {
using data = property<unsigned, data_class, &data_class::get_data>;
};
//used to produce informative errors
template <class T>
struct what_is;
//all 3 types below should, in theory, be the same
//but g++ says that test2_t is different
using target_t = property<unsigned, data_class, &data_class::get_data>;
using test1_t = typename my_classA::data;
using test2_t = typename my_classB<1>::data;
static_assert(std::is_same<target_t, test1_t>::value, ""); //this passes
static_assert(std::is_same<target_t, test2_t>::value, ""); //this does not
int main() {
what_is<test1_t> t1;
what_is<test2_t> t2;
}
I ran your code with c++11 because I'm not very familiar with c++14 yet. But all I replaced were the using (aliases) with typedefs and simplified the code a little bit. Nothing to affect its output.
I got the desired results by adding a typename T to the inherited classB template which when instantiated, it will replace the R with T, so in this case "unsigned".
#include <iostream>
#include <type_traits>
template <typename R, typename T, R(T::*P)() const>
struct property
{
static R get(const T& t)
{
return (t.*P)();
}
};
struct data_class
{
private:
unsigned m_data;
public:
unsigned get_data() const
{
return m_data;
}
};
struct my_classA : public data_class
{
typedef property<unsigned, data_class, &data_class::get_data> data;
};
template <typename T, int>
struct my_classB : public data_class
{
typedef property<T, data_class, &data_class::get_data> data;
};
int main()
{
typedef typename my_classA::data normClassA;
typedef typename my_classB<unsigned,1>::data tmplClassB;
std::cout<< std::is_same< property<unsigned, data_class, &data_class::get_data> , normClassA >::value <<std::endl;
std::cout<< std::is_same< property<unsigned, data_class, &data_class::get_data> , tmplClassB >::value <<std::endl;
}
The result is this:
~$g++ -std=c++11 test.cpp
~$./a.out
1
1
I think the problem has to do with the class template instantiation criteria because when I originally tried to print the sizeof's of the two classes, my_classA::data returned 1, but my_classB<1>::data ended in a compiller error. I'm still quite fuzzy as to why this occurs. Technically it should have instantiated the class template just fine. Maybe it's the property inside the classB template that was falsely instantiated. I'll look more into this but if you find the answer, please post it. It's an interesting one!
EDIT:
The original code works fine on Cygwin GCC 4.8.2. Result is 1 and 1. Maybe it's just a gcc4.9.2 compiler issue.
For me generic vectors of templates are vector that can take template with any argument list. Like this
vector<Foo<?>> foos;
foos.push_back(Foo<int>(5));
foos.push_back(Foo<Bar>(Bar()));
foos.push_back(Foo<string>("bar"));
EDIT:
This is why I need this
#ifndef EVENT_DISPATCHER_H
#define EVENT_DISPATCHER_H
// #include <boost/signals2.hpp>
#include <string>
#include <vector>
#include <functional>
#include <map>
namespace Whitedrop {
template <typename... T> class EventDispatcher {
public:
EventDispatcher(std::string eventID)
{
}
void on(std::function<void(T...)> callback)
{
mCallbacks.push_back(callback);
}
void trigger(T&... args)
{
for (auto f : mCallbacks)
f(args...);
}
protected:
std::vector<std::function<void(T...)>> mCallbacks;
};
std::map<std::string, EventDispatcher<?> > dispatchers; // HERE <--------
template<typename... T> void registerListener(std::string eventID, std::function<void(T...)> callback)
{
if (!dispatchers.count(eventID))
{
dispatchers[eventID] = new EventDispatcher<T...>(eventID);
return;
}
dispatchers.find(eventID)->second.on(callback);
//std::shared_ptr<Chunk> chunk = mChunks.find(pos)->second;
}
template<typename... T> void invokeListener(std::string eventID, T... args)
{
if (!dispatchers.count(eventID))
{
return;
}
dispatchers.find(eventID)->second->trigger(args...);
}
};
#endif
SInce it seems not possible, how can I resolve my issue?
No, that is not possible. Class templates are templates, not types. The std::vector template requires a type as its first argument, not a template.
You can use class templates to produce types, but you have to choose one particular type for each instantiation of the std::vector template.
More generally, the nature of a template parameter tells you what kind of argument you can use. In C++ there are three "ontological tiers": values ("things that have types), types ("things that are types), and templates ("things that make any of the three"). Each can appear as a template parameter:
template < int A // Value (int prvalue)
, typename B, // Type
, template <typename> class C // Template
> struct Foo {};
Foo<10, double, std::allocator> foo;
// A B C
Simple answer is no.
The compiler needs to figure out types and sizes.
EDIT
Use inheritance
Eg
class Event {
private:
std::string m_id;
public:
Event(std:string &id) : m_id(id) { }
std:string EveentId() const { return m_id;}
virtual void DoEvent() = 0;
};
class MyEvent : Event {
public:
MyEvent() : Event("MyEvent") { }
DoEvent() { std::cout << "MyEvent" << std::endl;
};
Then have a list of events
i.e.
std::vector<std::shard_ptr<Event>> events;
events.push_back<std::make_shared<MyEvent>());
events[0]->DoEvent();
std::vector is a homogeneous container, which means it can only contain one type. Note that Foo<> is a family of types not a single type, the type of std::vector is different depending on the template parameter.
Now, you can achieve what you want using two methods I can think off, the first is by erasing the type, for example you can use std::vector<boost::any>, but note that it completely erases the type (the type info is lost), and is not a compile time operation.
The second way is using a tuple, this is a compile time fixed-size container, which means you can't add new elements at runtime, because the type of each object is determined at compile time.
I have created a simple LinkedList class using templates in C++
Basically I can create an instance of my list like this
LinkedList<int> myList = LinkedList<int>();
Now I would like to add a method to my LinkedList and provide a callback function so that function can call back to my code to perform an action.
I tried to create the following
template< typename T>
typedef bool(*LinkedList_SortCallBack2)(T);
But I receive a compiler error
error C2998: 'bool (_cdecl *_cdecl LinkedList_SortCallBack2)(T)' : cannot be a template definition
as a work around I have used void * but is there a way to do what I want? so my call back is like this
bool cb(int NewValue, int ExistingValue)
{
}
instead of
typedef bool (*LinkedList_SortCallBack)(void *value1, void* value2);
bool cb(void* NewValue, void* ExistingValue)
{
int a, b;
a = *(int *)NewValue;
b = *(int*)ExistingValue;
if (a < b)
return true;
else
return false;
}
Typedefs cannot be templates.
In C++11, use aliases
template <typename T>
using callback = void (*)(T);
In C++03, put it inside a structure
template <typename T>
struct SortCallback {
typedef void (*)(T) type;
};
typename SortCallback<int>::type callback;
I'm trying to initialise a list of args to use with fusion::invoke.
The args are all of the form:
template <typename Type>
struct ArgWrapper
{
inline ArgWrapper(){}
inline void Setup(lua_State*L,int idx)
{
//setup this value from the lua state...
//in reality this class is specialised for different lua types
}
operator Type(){return value;}
Type value;
};
So I can do, for example
int add(int a,int b){return a+b;}
fusion::vector<ArgsWrapper<int>,ArgsWrapper<int> > v;
fusion::at_c<0>(v).value=1;
fusion::at_c<1>(v).value=2;
std::cout<<fusion::invoke(add,v)//prints 3
But if I have a fusion sequence of type FusionListType, where I know each type in the sequence is an ArgWrapper of some type, how can I iterate through that list and call the Setup function on each element (I have just one lua_State pointer and want to use it as the first argument for Setup, and I want to use the position in the sequence as the second argument).
So for a vector of size 3 I want the resultant logic to be:
lua_State*L;
fusion::at_c<0>.Setup(L,1);
fusion::at_c<1>.Setup(L,2);
fusion::at_c<2>.Setup(L,3);
I have tried:
template<typename ArgWrapperType,int N>
void FillArgWrapper(ArgWrapperType arg,lua_State*L)
{
fusion::at_c<N>(arg).Setup(L,N+1);
}
template<typename ArgWrapperType>
void FillArgWrapper<ArgWrapperType,0>(ArgWrapperType arg,lua_State*L)
{
fusion::at_c<0>(arg).Setup(L,1);
}
But this fails to compile, saying function template partial specialisation ‘FillArgWrapper<ArgWrapperType, 0>’ is not allowed.
Thanks in advance.
Ok, I figured it out. I need to be using a struct:
template <typename ArgWrapperList,u32 N=mpl::size<ArgWrapperList>::value-1>
struct ArgWrapperListFiller
{
static inline void Setup(ArgWrapperList &args,lua_State*L)
{
fusion::at_c<N>(args).Setup(L,N+1);
ArgWrapperListFiller<ArgWrapperList,N-1>::Setup(args,L);
}
};
template <typename ArgWrapperList> //base case, do not recurse
struct ArgWrapperListFiller<ArgWrapperList,0>
{
static inline void Fill(ArgWrapperList &args,lua_State*L)
{
fusion::at_c<0>(args).Setup(L,1);
};
};
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();
}
};