在我们的代码中,我们有以下类:
template<class A, class B>
class myClass
{
typedef std::list<Object<A,B>> MyList;
typedef std::map<A, typename mList::iterator> MyMap
MyList mList;
MyMap mMap;
}
A类是元编程的,它可以是字符串,int等。 我想更改代码,以便在类A是“元字符串”的情况下使用地图,否则将使用unordered_map。
我尝试添加更多元编程但尚未成功:
template< class A, class B>
struct MapType // default
{
typedef std::list<Object<A,B>> MyList;
typedef std::unordered_map<A,B> MyMap;
}
//TODO struct with templated A (string) to use std::map
template<class A, class B>
class myClass
{
???? // if A ~ String define myMap to MAP . otherwise unordered
MyList mList;
MyMap mMap;
}
使用不同地图类型的任何其他建议也将受到赞赏。
由于
答案 0 :(得分:3)
一个简单的解决方案是使用std::conditional
检查A
是否与您的“元字符串”类相同(我选择std::string
进行演示):
template<class A, class B>
class myClass
{
std::list<Object<A,B>> mList;
std::conditional_t<std::is_same<A,std::string>::value,
std::map<A,B>, std::unordered_map<A,B>> mMap;
};
另一种可能性是使用部分专业化:
template<class A, class B>
class myClass
{
std::list<Object<A,B>> mList;
std::unordered_map<A,B> mMap;
};
template<class B>
class myClass<std::string,B>
{
std::list<Object<std::string,B>> mList;
std::map<std::string,B> mMap;
};
答案 1 :(得分:2)
使用std::conditonal特质:
template<class A, class B>
class myClass
{
using MyList = std::list<Object<A,B>>;
using MyMap = std::conditional_t<IsMetaString<A>::value,
std::map<A, typename mList::iterator>,
std::unordered_map<A, typename mList::iterator>>;
MyList mList;
MyMap mMap;
}
请注意我冒昧地使用使用类型别名替换你的tyedef,你也应该这样做。
剩下的就是实现IsMetaString
,这取决于你对Meta String的定义可以简单如下:
template <class T> struct IsMetaString : std::false_type {};
template <> struct IsMetaString<std::string> : std::true_type {};
例如,如果使用元字符串,则表示std::string
。或者您可以根据需要对其进行修改。
我认为你的意思是typename MyList::iterator
而不是typename mList::iterator
。 子>
答案 2 :(得分:0)
假设“元字符串”的类型为foo
(我刚刚编造的虚构名称,因为您尚未指定“元字符串”是什么,您只需执行
template< class A, class B>
struct MapType // default
{
typedef std::list<Object<A,B>> MyList;
typedef std::unordered_map<A,B> MyMap;
MyList mList;
MyMap mMap;
};
template<class B>
struct MapType<foo, B>
{
typedef std::list<Object<foo, B>> MyList;
typedef std::map<foo,B> MyMap;
MyList mList;
MyMap mMap;
};
答案 3 :(得分:0)
使用部分特化(用于pre-C ++ 11,可能没有std :: conditional),你不需要专门化整个类(这可能是复制很多方法的一大负担) ,但你可以只专注地图类型:
template<class A, class B>
class myClass
{
template<class X, class ITER_T>
struct map_type {
typedef std::map<X, ITER_T> type;
};
template<class ITER_T>
struct map_type<std::string, ITER_T> {
typedef boost::unordered_map<A /* or std::string */, ITER_T> type;
};
typedef std::list<Object<A,B>> MyList;
typedef map_type<A, typename MyList::iterator>::type MyMap;
MyList mList;
MyMap mMap;
};
(对于pre-C ++ 11,我使用boost::unordered_map
代替std::unordered_map
)