Hi i have a c++ class with some private members as follows
template <typename V, typename E>
class Vertex
{
public:
Vertex();
~Vertex();
typedef std::pair<int, E> edgVertPair;
typedef std::vector<edgeVertPair> vectEdges;
void setVertexID(int data);
int getVertexID();
void setEdgeVertPair(int vertID, E edge);
edgVertPair getEdgeVertPair();
void setEdgeList(edgeVertPair edgeVert);
vectEdges getEdgeList();
private:
int vertexID;
edgVertPair evp;
vectEdges edgeList;
};
Now i want to create a pair i.e. something like
evp.first="someint";
evp.second="somestring";
and then push this evp into the edgeList i.e. edgeList.push_back(evp);
Now the problem is in the setter function i did something like this:
template<typename V, typename E>
void Vertex<V, E>::setEdgeVertPair(int vertID, E edge){
...populate evp;...
}
now i don't know how to populate the evp pair with vertID, edge.
Use std::make_pair to populate the evp pair.
http://www.cplusplus.com/reference/std/utility/make_pair/
Thanks to all who replied to my question, i figured it out after some search. one way was i removed the typedef's and in my private data section, declared the variables directly as
std::pair<int, E> evp;
std::vector<std::pair<int, E>> edgeList;
and that worked fine.
the other way was i had to prepend the keyword 'typename' before typedef's and it worked.
Related
Lets say we have some pair like class:
class PairLike{
public:
string key;
int val;
PairLike(string Key, int Val) : key(Key), val(Val){};
//...other members
};
A few objects to go along with it:
PairLike p1("a",1);
PairLike p2("b",2);
PairLike p3("c",3);
PairLike p4("d",4);
Is there a way of automatically working with this object?
For example, something similar to:
std::map<PairLike> container = {p1,p2,p3};
container.insert(p4);
Instead of writing something like:
std::map<string, int> container = {{p1.key, p1.val}, {p2.key, p2.val}, ... }
container.insert({p4.key, p4.val})
I'm aware that using an std::set<PairLike> with a comparator using is_transparentcan achieve the result I'm looking for. However, I am curious if there is any way to approach this problem with a map.
You could provide a conversion operator for converting to std::pair:
class PairLike{
public:
// ...
operator std::pair<const std::string, int>() {
return {key, val};
}
};
And use it like:
std::map<string, int> container{p1,p2,p3};
container.insert(p4);
Edit: please see the #krisz's answer for viable alternative that I overlooked here.
That is not possible. std::pair is defined as part of the class definition, and cannot be altered to a custom class.
P.S. As noted by #UnholySheep, it's defined in the CPP standard:
namespace std {
template<class Key, class T, class Compare = less<Key>,
class Allocator = allocator<pair<const Key, T>>>
class map {
public:
// types
using key_type = Key;
using mapped_type = T;
using value_type = pair<const Key, T>;
...
I was wondering if this was a valid way to assign a multidimensional map inside of a class method and if not how would I go about doing this.
template<typename T>
std::map<std::string, std::map<std::string, T>> MT;
template<typename T>
void MonsterTemplate(std::string name, std::string node, template T v) {
MT[name][node] = v;
}
Edit1: I compiled and it gave me many errors but I will just give a portion of the 1st.
error C3376: 'MonsterType::MT': only static data member templates are allowed
Edit2:
I tried creating a struct
template<typename T>
struct Wrapper
{
typedef std::map<std::string, std::map<std::string, T>> MT;
};
I then added this inside the class
template<typename T>
Wrapper<T>::MT mt;
template<typename T>
void MonsterTemplate(std::string name, std::string node, template T v) {
mt[name][node] = v;
}
Then got this error amongst many others.
warning C4346: 'MT': dependent name is not a type
The struct works outside the class without being multidimensional map, but I am unsure how to access it as multidimensional map.. just trying different things.
The idea is I want to store data of several objects data and index them by name, node and value.
Edit3:
So this is what I went with, and haven't gotten an error (just yet :p)
std::map<std::string, std::map<std::string, int>> MT;
void MonsterTemplate(std::string name, std::string node, int v) {
MT[name][node] = v;
}
Just updating this for anyone looking for something similar
So I figured out how to construct this.
template<typename T>
struct Test
{
std::map<std::string, std::map<std::string, std::map<size_t, std::map<std::string, T>>>> testmap;
void MonsterTemplate(std::string creatureName, std::string name, std::string node, T v) {
size_t i = testmap[creatureName][name].size();
testmap[creatureName][name][i][node] = v;
}
};
Test<std::string> str;
Since I needed various data types for T the structure worked much better than trying to find a way to assign a template to a static class, I am only using std::string as an example.
This can then be used inside of the class's method since str has a global scope.
str.MonsterTemplate(creatureName, name, node, value);
I'm working through some old exam papers without the memos. I just want to make sure I am understanding this correctly.
Provide an interface of the template class
Dictionary <Tkey, TValue>
This is the scenario provided
class Dictionary {
public:
Dictionary();
void Add(int key, const string &value);
string Find (int key) const;
private:
vector<int> Keys;
vector <string> Values;
};
This is the solution I have written down
class Dictionary {
public:
Dictionary();
void Add(TKey key, const TValue &value);
TValue Find (TKey key) const;
private:
vector <Dictionary> Keys;
vector <Dictionary> Values;
};
This appears correct to me. I haven't compiled a driver program for this as I just want to make sure I am understand this correctly given the template class.
I think just the last 2 lines where vector is concerned is what I want to make sure I've written correctly.
Thanks for taking the time.
You should simply follow your instructions:
template<typename Tkey, typename TValue> // <<<<<<<<
class Dictionary {
public:
Dictionary();
void Add(TKey key, const TValue &value);
TValue Find (TKey key) const;
private:
vector <TKey> Keys; // <<<<<<<<
vector <TValue> Values; // <<<<<<<
};
Or even better (since it's going to be hard to associate those vector members appropriately):
template<typename Tkey, typename TValue> // <<<<<<<<
class Dictionary {
public:
Dictionary();
void Add(TKey key, const TValue &value);
TValue Find (TKey key) const;
private:
vector <std::pair<TKey,TValue>> dict; // <<<<<<<
};
This conversion is incomplete, and slightly incorrect.
To make it complete, make sure the class is actually a class template, i.e. there is
template <typename TKey, typename TValue>
class Dictionary {
...
};
The correction is to make the two vectors take keys and values. Currently, both vectors are set to store Dictionary elements, which is not what you need: the first vector should hold TKey elements, while the second one should hold TValues. You would discover this shortcoming as soon as you'd start implementing your Dictionary<TKey,TValue>::Find method.
I have a template, which may be used with different stl map (map<int, int>, map<int, char>, etc.), as follows.
template <typename Map> struct TriMaps
{
Map& next;
Map& prev;
Map& curr;
};
so, TriMaps<init, int> intTriMaps; TriMaps<int, char> charTriMaps;
Then, is it possible to have a container of the above TriMaps, in different type? e.g.
vector <TriMaps> vecMaps;
which contain intTriMaps and charTriMaps? Usually container requires the same type. But I really need a container for my case. No boost or third library available.
First determine and finalize what this class template TriMaps is expected to do. In C++, you must initialize a reference to something. You probably need a non-reference type (or a pointer type). Consider:
template <typename Map>
struct TriMaps
{
Map next;
Map prev;
Map curr;
};
Usage:
TriMaps<int> IntMaps;
vector<TriMaps<int>> iv;
If you need two template type argument, you can do this way:
template <typename MapType1, typename MapType2>
struct TriMaps
{
MapType1 a;
Maptype2 b;
};
Usage:
TriMaps<int, float> IntMaps;
vector<TriMaps<int, float>> iv;
EDIT:
Carefully understand that following simple class will not compile.
class TriMap
{
int & ref_int;
};
One approach is to refer a global variable (just to make it compile), or take an int& via a constructor.
// Approach 1
int global;
class TriMap
{
int & ref_int;
public:
TriMap() : ref_int(global) {}
};
// Approach 2
class TriMap
{
int & ref_int;
public:
TriMap(int & outer) : ref_int(outer) {}
};
You can't have a std::vector of different type
but if you can have base class
struct TriMapBase { virtual ~TriMapBase() = default; };
template <typename Map> struct TriMaps : TriMapBase { /* Your implementation */ };
Then you may have:
TriMapBase<std::map<int, int>> mapint;
TriMapBase<std::map<int, char>> mapchar;
std::vector<TriMapBase*> v = {&mapint, &mapchar};
but you have to use virtual functions
or dynamic_cast to retrieve the correct type afterward...
or use
I have been implementing a visual debugger in my application using another bit of source code. I ran into an issue when I stumbled across them using this..
struct DebugVertex
{
gkVector3 v;
unsigned int color;
};
typedef utArray<DebugVertex> Buffer;
I found the free library that they are using for utArray, however I like to stick with the included libraries when possible (it seems like they used external libs just cause). This is what the definition of utArray looks like...
template <typename T>
class utArray
{
public:
typedef T *Pointer;
typedef const T *ConstPointer;
typedef T ValueType;
typedef const T ConstValueType;
typedef T &ReferenceType;
typedef const T &ConstReferenceType;
typedef utArrayIterator<utArray<T> > Iterator;
typedef const utArrayIterator<utArray<T> > ConstIterator;
public:
utArray() : m_size(0), m_capacity(0), m_data(0), m_cache(0) {}
utArray(const utArray<T>& o)
: m_size(o.size()), m_capacity(0), m_data(0), m_cache(0)
{
reserve(m_size);
copy(m_data, o.m_data, m_size);
}
Is there anything similar I can use? I am not experienced defining a type based on a struct array so any help would be appreciated.
It looks a lot like a std::vector to me ... (#include <vector>)
From all standard sequence STL containers probably vector & deque are closest to an array (at least to me, I associate random access with arrays...).
The only problem you would have is that STL containers have different naming conventions for the internal typedefs like: iterator, pointer, value type & so on. If you really like typing Buffer::Iterator instead of Buffer::iterator then you'll need to have a proxy type over the STL type of your choosing. Something like:
#include <vector>
template <typename T>
class utArray
{
private:
typedef std::vector<T> InnerContainer;
InnerContainer m_innerContainer;
public:
typedef typename InnerContainer::pointer Pointer;
typedef typename const InnerContainer::pointer ConstPointer;
typedef typename InnerContainer::value_type ValueType;
typedef const typename InnerContainer::value_type ConstValueType;
typedef typename InnerContainer::reference ReferenceType;
typedef typename InnerContainer::const_reference ConstReferenceType;
typedef typename InnerContainer::iterator Iterator;
typedef typename InnerContainer::const_iterator ConstIterator;
public:
utArray() {}
utArray(const utArray<T>& o)
: m_innerContainer(o.m_innerContainer)
{
}
};