I have a hash table class. It has a template parameter hashFunction:
#include <string>
template<class KeyType> using hashFunction_t = size_t(size_t, const KeyType&);
template< class KeyType, class ValueType, int nHashGroups,
hashFunction_t<KeyType> hashFunction >
class HashTable
{
};
class Entity
{
//djb2
size_t stringHash(size_t nGroups, const std::string& key)
{
unsigned long hash = 5381;
const char* str = key.c_str();
int c = 0;
while (c = *str++)
hash = ((hash << 5) + hash) + c;
return hash % nGroups;
}
HashTable <std::string, int, 10, stringHash> ht;
};
int main()
{
Entity{};
}
I would prefer to hide stringHash function inside the Entity class as a private function but doing that gives me an error:
Error (active) E0458 argument of type
"size_t (Entity::*)(size_t nGroups, const std::string &key)"
is incompatible with template parameter of type
"hashFunction_t<std::string> *"
How can I do this?
The problem is that you are trying to use a pointer-to-member as a type template parameter, and this is not supported, basically because when you define a type you don't bind that type to any specific object.
When (as suggested in a comment) you make stringHash static, then you no longer need the object, so it can be used to define the type.
If you still need to have stringHash from a non-static member, then you can change the template to something like the below. Be aware that you have to pass the object to the HashTable in order to call the hashFunction. Also, keep an eye on the syntax to call it.
template<class KeyType, class Obj> using hashFunction_t =
size_t(Obj::*)(size_t, const KeyType&);
template< class KeyType, class ValueType, int nHashGroups,
class Obj, hashFunction_t<KeyType, Obj> hashFunction>
class HashTable
{
public:
explicit HashTable(Obj& obj) : m_obj{obj} {
(m_obj.*hashFunction)(10, ""); // arguments just for illustrative purposes
}
private:
Obj& m_obj; // keep a reference to the object to call the method
// be careful with dangling references
};
class Entity
{
size_t stringHash(size_t nGroups, const std::string& key)
/* ... */
// Pass a reference to the object
HashTable <std::string, int, 10, Entity, &Entity::stringHash> ht{*this};
};
Related
I am trying to create an instance of a templated class, based on the template type of another class. But I am getting the following error.
error: template argument 1 is invalid
Here is a minimal example to reproduce the error
template <typename IdType>
class GraphNode
{
IdType id;
};
template <typename IdType>
class Graph
{
public:
using NodeType = IdType;
GraphNode<IdType> nodes[100];
};
template <typename IdType>
class ProcessGraph
{
//some functions
};
template <typename IdType>
auto create_graph()
{
Graph<IdType> graph;
// populate graph here
return graph;
}
int main(int argc, char *argv[])
{
if(atoi(argv[1]))
const auto &graph = create_graph<int>();
else
const auto &graph = create_graph<unsigned long>();
auto processor = ProcessGraph<typename graph.NodeType>(); // The error occurs here
return 0;
}
Thanks for help
There are two problems in your code:
The graph variable has a different type in the branches, and it is out of scope when declaring processor.
The syntax to access an inner type alias is wrong.
You can retrieve the type of a variable x using decltype(x). Since graph is a reference, you need to remove the reference using std::remove_reference_t. Afterwards, you can use ::NodeType to retrieve the inner type alias.
if(atoi(argv[1]))
{
const auto &graph = create_graph<int>();
auto processor = ProcessGraph<
std::remove_reference_t<decltype(graph)>::NodeType>();
}
else
{
const auto &graph = create_graph<unsigned long>();
auto processor = ProcessGraph<
std::remove_reference_t<decltype(graph)>::NodeType>();
}
If you want to refactor the code to avoid repetition, place the code that initializes the processor variable in a template function that gets graph as a parameter (or that creates graph in its body with a user-defined type).
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.
I was trying to built atop the thread here: Variable length template arguments list?
to have a default Functor class, this is only of academic interest. My goal is to build a generic Fucntor class: given a class name, method name and argument types(of variable length), it builds a class that has an operator() method which takes variable number of arguments of type specified in template args and takes a pointer and applies the given method. Imagine a class thus:
class MyClass
{
public:
float Fraction( float n, int m)
{
return n/m;
}
int Increment(int n)
{
return n+1;
}
} ;
And a templatized functor class that can be used in any function thus:
int k = FunctorClass<MyClass, Increment, int, int /*return type*/> (3);
assert(k == 4);
float l = FunctorClass<MyClass, Fraction, float, int, float, /*return type*/> (4,3);
assert(l == (4/3));
Can such a functor class be constructed?
Sidenote: Cant use Variadic templates, (building in VS2010, no ... template arguments)
Thanks for the help
This is certainly doable, e.g. Boost bind() uses this approach under the hood. Without variadics you won't get full generality, however, because you will be limited to a fixed number of template arguments and you need to type the implementation for each different number of arguments you want to support. Also, without rvalue references you won't get perfect forwarding.
That said, the way you are trying to use it won't work: when stating the member functions, you can't just name them. You need to obtain the correct member function point using e.g. &MyClass::Increment and &MyClass::Fraction. If the member function is overloaded, you need to disambiguate it.
Since you apparently want to enable the use of this function object for non-static member functions, you also need to provide an object on which the member function is to be called. The most reasonable approach for this is to pass a reference to the object as a constructor argument of the function object class and to store it to be used whenever the function is being called. That is, the use looks somewhat different but it can be simplified with some sort of factory function. Here is a version which adjusts the various things and implements a corresponding function object template:
#include <cassert>
// -----------------------------------------------------------------------------
template <typename T, T> class FunctorClass;
template <typename RC, typename Class,
RC (Class::*Member)()>
class FunctorClass<RC (Class::*)(), Member>
{
public:
FunctorClass(Class& object): object_(&object) {}
RC operator()() const { return (this->object_->*Member)(); }
private:
Class* object_;
};
template <typename RC, typename Class, typename A0,
RC (Class::*Member)(A0)>
class FunctorClass<RC (Class::*)(A0), Member>
{
public:
FunctorClass(Class& object): object_(&object) {}
RC operator()(A0 a0) const { return (this->object_->*Member)(a0); }
private:
Class* object_;
};
template <typename RC, typename Class, typename A0, typename A1,
RC (Class::*Member)(A0, A1)>
class FunctorClass<RC (Class::*)(A0, A1), Member>
{
public:
FunctorClass(Class& object): object_(&object) {}
RC operator()(A0 a0, A1 a1) const { return (this->object_->*Member)(a0, a1); }
private:
Class* object_;
};
// -----------------------------------------------------------------------------
class MyClass
{
public:
int foo() { return 17; }
float Fraction( float n, int m)
{
return n/m;
}
int Increment(int n)
{
return n+1;
}
};
int main()
{
MyClass object;
int i = FunctorClass<int (MyClass::*)(), &MyClass::foo>(object)();
assert(i == 17);
int k = FunctorClass<int (MyClass::*)(int), &MyClass::Increment>(object)(3);
assert(k == 4);
float l = FunctorClass<float (MyClass::*)(float, int), &MyClass::Fraction>(object)(4,3);
assert(l == (4.0f/3));
}
I'm not sure you would need variadics to pull this off. Consider the following interface...
template < typename RETURN_TYPE >
class iFunctor abstract {
public:
virtual RETURN_TYPE operator () ( void ) = 0;
};
Abstract interfaces are not full-blown classes, they can contain a partial implementation such as function signatures and some data members. With the template, you can generalized a return type. But what about the argument list you say?
Note how there is no constructor in the interface. In your concrete class (or derived classes) you can pass the burden of variable argument lists to the constructor, like so...
template < typename TYPE >
class ConcreteFunctor_add : public iFunctor < TYPE > {
private:
int A;
int B;
public:
explicit ConcreteFunctor_add ( const int &a, const int &b ) : A(a), B(b) {};
TYPE operator () ( void ) { return ( A + B ); };
};
You deal with the argument list on a case by case basis through the constructor.
The explicit constructor requires an argument list upon declaration, so you'll get your variable list here. So in practice...
ConcreteFunctor_add < int > addInteger ( 10, 10 );
addInteger();
...and you'd be cool.
I am attempting to write a function which will operate on a std::map of any key and class pointer given to it, and create a new std::map with an index based on the return value of a function in the class. Essentially, a template function to re-index a map based on a function in its contained class. However, I am having compiler errors when trying to invoke the function.
template<class AnyType, class ValueType, class FunctionType>
AssocArray<FunctionType,ValueType> reindex( const AssocArray<AnyType, ValueType>& original, FunctionType (*getterFunction)() ) {
AssocArray<FunctionType, ValueType> ret;
FunctionType index;
for(typename AssocArray<AnyType,ValueType>::const_iterator it = original.begin(); it!=original.end(); it++) {
index = ((*it->second).*getterFunction)();
ret[index] = it->second;
}
return ret;
}
Invoked by:
floatIndexed = reindex( intIndexed, &test::getB );
Where getB is of float type.
This results in the compiler error:
src/World.cpp:78:50: error: no matching function for call to ‘reindex(std::map<int, onathacar::test*>&, float (onathacar::test::*)())’
src/World.cpp:78:50: note: candidate is:
./include/Types.h:123:36: note: template<class AnyType, class ValueType, class FunctionType> std::map<PreservedType, ValueType> onathacar::reindex(const std::map<LookupType, ValueType>&, FunctionType (*)())
I have tried different variations of this, including using "FunctionType (ValueType::*getterFunction)()" and changing "AssocArray" to "AssocArray". The only one which worked added a fourth template argument:
template<class AnyType, class ValueType, class FunctionType, class SomeType>
AssocArray<FunctionType,ValueType> reindex( const AssocArray<AnyType, ValueType>& original, FunctionType (SomeType::*getterFunction)() ) {
However, this seems like it would potentially allow functions that are not actually members of ValueType to be called, and so I would prefer some other option. I am not even sure what is wrong, as it appears the templates match, at least with the addition of "ValueType::". Why does the call not match the template, and is there a way to fix it without a fourth templated type?
For more context, Header Containing Implementation and Calling Function.
You have two problems. The first is that reindex implies that the value types are values, but you use them as pointers:
AssocArray<float, test*> floatIndexed;
floatIndexed = reindex( intIndexed, &test::getB );
The second is that reindex's second parameter needs to be declared as a member function, not a free function. So reindex should look like this:
template<class AnyType, class ValueType, class FunctionType>
AssocArray<FunctionType,ValueType *> reindex( const AssocArray<AnyType, ValueType *>& original, FunctionType (ValueType:: *getterFunction)() ) {
AssocArray<FunctionType, ValueType*> ret;
FunctionType index;
for(typename AssocArray<AnyType,ValueType*>::const_iterator it = original.begin(); it!=original.end(); it++) {
index = ((*it->second)->*getterFunction)();
ret[index] = it->second;
}
return ret;
}
It seems that you are trying to use your rindex() function with members but your function is declared to use non-members. This won't work. The reason this won't work is that the you need an object to access either function or data members of a class.
template<class A, class B>
class X{
public:
};
class Y{
public:
int func() { return 42; }
};
template<class A, class B, class C>
X<C,B> reindex( const X<A, B>& original, C (B::*getterFunction)() ) {
X<C, B> x2;
cout << "hello" << endl;
return x2;
}
int main() {
X x1;
reindex(x1,&Y::func);
return 0;
}
This works and gives perfectly valid results.
The problem with your call AssocArray intIndexed, is the fact that you are trying to pass &test::getB as the getter function, which assumes valueType = test, where as your actual value type, is test*.
I'll begin with a context that will lead to the actual question.
I'm trying to build a class whose every instance will manage how data is tied together into objects.
The class should preferably contain methods:
class DataManager {
Object CreateObject();
void DestoryObject();
template<typename DataType>
DataType* AddDataToObject(Object o)
template<typename DataType>
DataType* GetDataForObject(Object o)
template<typename DataType>
void RemoveDataFromObject(Object o)
};
Object in the code above is just some identifier - int at this point and does not contain any data or methods (this should not change). DataType used above can be basically any class, however the general situation is that this is just a struct with no methods. The complete list of things that can be used as DataType is known at compile time but should not be encoded as it changes quite often.
The two goals I try to achieve are:
- Maintainability/Speed - The user should be able to add new DataType structures without modifying this code
- Speed - should be as fast as possible :)
Now the best thing idea I had so far is to make a container classes:
class ContainerBase;
template<typename DataType>
class DataTypeContainer : ContainerBase;
The data structure then would be something like:
map< DataTypeType, map< Object, ContainerBase* > >
Sow how can one achieve this?
Would boost::mpl::map help and how?
In essence this should be possible to do since all DataType's are known at compile time.
class DataManager {
struct internal_base { virtual ~internal_base() {} };
template<typename T> struct internal_data : public internal_base {
T t;
};
boost::unordered_map<Object, boost::unordered_map<std::string, boost::unique_ptr<internal_base>>> data;
public:
Object CreateObject() { return Object(); }
void DestroyObject(Object o) { data.erase(o); }
template<typename DataType> DataType* AddDataToObject(Object o, std::string name) {
internal_data<T>* ptr = new internal_data<T>();
data[o][name] = ptr;
return &ptr->t;
}
template<typename DataType> DataType* GetDataForObject(Object o, std::string name) {
internal_base* ptr = data[o][name].get();
if (internal_data<DataType>* dptr = dynamic_cast<internal_data<DataType>*>(ptr)) {
return &dptr->t;
else
return 0;
}
void RemoveDataFromObject(Object o, std::string name) {
data[o][name] = 0;
}
};
This code makes some assumptions- like default-construction of Object type, and that it is hashable. But it shouldn't be too difficult to modify. It would be substantially trickier to get defined behaviour if you want just one data member of each type associated with a specific Object, because you can't rely on RTTI to return unique names for each possible DataType.
If you want the equivalent of a map from types to values, and it can be global, you can use static members:
template <typename T>
struct DataManager {
static std::map<void*, Object> this_type_map;
};
plus appropriate definitions of DataManager<T>::this_type_map for the various values of T (but those definitions don't need to be in the same source file). After that, you can create type map objects using (void*)(new int), free them using delete (int*)(m), and look up the object for an instance m and a type T using DataManager<T>::this_type_map[m]. You would want to wrap these in functions or objects, of course. Note that you can have a different type than Object as the value type in the map, including (using template specializations) having a different value type for each key type in the type map.
I think that you need the std::tuple c++11 or playing with boost::tuple for c++ 03
template<typename T>
struct Entry{
T t;
};
int main(int argc, char **argv) {
std::tuple< int, float, double, Entry<int> > objects;
std::get<0>(objects) = 3;
std::get<3>(objects).t = 5;
//
utils::get< Entry<int> >(object).t = 5;
return 0;
}
get by type can be implemented like here:
https://github.com/alekstheod/tnnlib/blob/master/src/Utilities/Utilities/MPL/Tuple.h
You could create a tuple with the mapping between your types like that:
template < std::size_t sz, typename... Types >
struct TypeMap {
TypeMap (std::array< std::tuple< Types... >, sz > m) : mapping (m) {
}
std::array< std::tuple< Types... >, sz > mapping;
};
Then specify a function to convert
template < typename To, typename From, std::size_t sz, typename... T >
To convert (From from, TypeMap< sz, T... > m) {
for (auto entry : m.mapping) {
if (utils::get< From > (entry) == from) {
return utils::get< To > (entry); //Tricky part here
}
}
throw std::logic_error ("No entry in the typemap");
}
Then specify the mapping
const auto map = TypeMap{{std::make_tuple (red, "red", 1),
std::make_tuple (green, "green", 2),
std::make_tuple (blue, "blue", 3)}};
and finally you can call your convert function and convert any type to any other type ;)
See my article here:
https://cpptelepathy.wordpress.com/
You would need this file
https://github.com/alekstheod/tnnlib/blob/master/src/Utilities/MPL/Tuple.h
for util::get