通常在模板中你想知道整个类型,但在我的情况下我需要知道更多,并希望"分解"类型.举个例子:
template <typename Collection<typename T> >
T get_front(Collection const& c)
{
return c.front();
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?注意:我需要它来自动推断类型,而不是传递类似的东西<std::vector<int>, int>
编辑:最后可以找到C++ 0x方式.
编辑2:我是傻了,一个办法较短C++ 98/03的方式比这一切特质的东西可以在答案的末尾.
如果您希望您的函数适用于任何仲裁标准库容器,则需要提取一些模板枪.
问题是,不同的容器采用不同数量的模板参数.std::vector,std::deque和std::list例如取2:底层项类型T和分配器类型Alloc.std::set并且std::map,另一方面分别取3和4:两者都具有的密钥类型K,地图另需值类型V,那么这两个取比较器Compare类型和分配器类型Alloc.您可以在此处获得标准库提供的所有容器类型的概述.
现在,对于模板枪.我们将使用部分专业的traits metastruct来获取基础项类型.(我使用class而不是typename纯粹的偏好.)
template<class T>
struct ContainerTraits;
// vector, deque, list and even stack and queue (2 template parameters)
template<
template<class, class> class Container,
class T, class Other
>
struct ContainerTraits< Container<T,Other> >{
typedef T value_type;
};
// for set, multiset, and priority_queue (3 template parameters)
template<
template<class, class, class> class Container,
class T, class Other1, class Other2
>
struct ContainerTraits< Container<T,Other1,Other2> >{
typedef T value_type;
};
// for map and multimap (4 template parameters)
template<
template<class, class, class, class> class Container,
class Key, class T, class Other1, class Other2
>
struct ContainerTraits< Container<Key,T,Other1,Other2> >{
typedef Container<Key,T,Other1,Other2> ContainerT;
// and the map returns pair<const Key,T> from the begin() function
typedef typename ContainerT::value_type value_type;
};
Run Code Online (Sandbox Code Playgroud)
现在准备完成了,就get_front功能了!
template<class Container>
typename ContainerTraits<Container>::value_type
get_front(Container const& c){
// begin() is the only shared access function
// to the first element for all standard container (except std::bitset)
return *c.begin();
}
Run Code Online (Sandbox Code Playgroud)
唷!就是这样!在Ideone上可以看到完整的示例.当然,有可能进一步改进,直到返回映射到a中的键的实际值std::map,或者使用容器特定的访问函数,但我只是有点懒得去做.:P
编辑
甲方式更容易的C++ 0x的方法是使用新的尾返回型函数的语法,其中的一个例子,可以发现在这里Ideone.
编辑2
嗯,我不知道为什么,但typedef在写这个答案时我完全没有想到嵌套的.我会让详细的方式作为特征类/模式匹配模板的参考.这是做到这一点的方式,它与我对traits类的做法基本相同,但最终不那么冗长.