C++实现任意类型键值存储的字典

初衷:

由于程序开发,需要一个容器能带索引功能的存储lamada。通过索引来获取特定索引的lamda表达式。这然我想到了map。但是map的键值必须是同类型。于是有了想编写一个能存储不同类型lamada的map。

说明:

python中的数据结构允许存储不同类型的数据,这非常方便。但c++没有相关功能的容器。或许是本人见识太少,也许有。如果有还希望看此博文的各位前辈能告知一下小弟,在此表示感谢!

不管怎样,已经萌生了要写这种容器的念头,也就难以姑息了。最开始的想法立马想到的就是c++泛型(template,auto)。但令人头痛的问题就是,无论是auto还是template都需要在编译的时候确定类型。否则无法编译通过。例如以下:

tempalte<typename T,typename U>
class Key
{
public:
   T mKey;
   U mVal;
}
在使用此类的时候,需要做如下声明:

Key<string,int> k;
而如果添加进入auto,例如:

class Key
{
public:
   auto mKey;
   auto mVal;
}
编译器无法确定变量类型,无法通过。


那假如将两者结合呢,有没有可能?

于是做了以下的辩想:

首先,要让一个容器能存储不同类型的变量,则其在声明的时候不能指定数值类型,例如Key<string,int>。但使用泛型是必须的,于是在声明容器类的时候,将template声明置于特定变量是合理的,例如:

class Key
{
template<typename T>
T mKey;
template<typename U>
U mVal;
}
但是以上的代码在编译的时候就已经过不了了:error C3857: 不允许使用多个 模板 参数列表。

有一个解决方法,就是不声明变量,转而声明成员函数,但这个函数必须类似于C#的属性一样,它必须实现对一个成员变量的取值和赋值。于是有了以下的声明:

class Key
{
public:
template<typename T>
auto mKey(T t)->decltype(T){return u;};
tepmlate<typename U>
auto mVal(U u)->decltype(U){return t;};
}
但在使用时无法编译:error C2893: 未能使函数模板“unknown-type Key::mKey(T)”专用化。以上是强迫症造成的,可以将auto去掉。

class Key
{
public:
template<typename T>
T mKey(T t){return t;};
tempalte<typename U>
U mVal(U u){return u};
}
这样,就可以不用在声明Key的时候指定类型了。但另一个麻烦的问题出现了,就是存储问题。编译器为Key开辟了一份内存,却没有开辟空间给存储数值,因为你没有声明用于存储的成员变量。无论是以下两种写法的一种,都无法使用:

一:
class Key
{
public:
template<typename T>
T mKey(T t){key=t;return key;};
T key;
template<typename U>
U mVal(U u){val=u;return val;};
U val;
}

二:
class Key
{
public:
template<typename T>
T mKey(T t){key=t;return key};
template<typename T>
T key;

template<typename U>
U mVal(U u){val=u;return val;};
template<typename U>
U val;
}
那么问题来了,如何存储变量,因为不能声明成员变量。有个解决的方法,就是利用lamada。lamada具有捕捉上文变量的功能,若将lamada用function类型来存储,就可以将上文中的变量存储在lamada之中。编译器为lamada声明了一份内存,同时其中也为上文中的变量声明了空间。这是好事。那么可以在Key类中声明两个function变量来存储lamada。

class Key
{
public:
	Key(){};
private:
	tr1::function<void* ()> mKey;
	tr1::function<void* ()> mVal;
public:
	template < typename U >
	U& Key(U u){ 
		U *b =& u;
			mKey = [=]()->void*
			{
				return b;
			};
			
			return *((U*)mKey());
	};

	template < typename V >
	V& Val(V t){ 
		V *b = &t;
			
			mVal = [=]()->void*
			{
				return b;
			};
			bValInit=true;
			return *((V*)mVal());
	};
};
这个类可以实现存储任何类型的变量,但有很多可以改进的地方,这里就不贴出改进的地方。只阐述了想法就可以了。再配合一下容器类就实现了一个map:

template<typename T>
class vMap
{
public:
	vMap(void){};
	~vMap(){};
	void Add(vKey k){vKeys.push_back(k);};
	vKey& operator[](T v){
		for (int n = 0; n < vKeys.size(); n++)
		{
			if (vKeys[n].Key(v) == v)
				return vKeys[n];
		}
		return NULLKEY;
	};
private:
	vector<vKey> vKeys;
};
注意到了我用于存储Key的是一个vector。在搜寻值时用了for循环。这样时间度就是omega(n)。这时一个线性递增的过程。后续会想提高效率。若有读者有好的想法,欢迎建议。谢谢!









  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值