假设您有一个接受以下通用容器的函数模板T
:
template <typename ContainerT>
void DoThings(ContainerT const& input)
{
// Do something
}
在此方法中,您想要获取容器中某物的迭代器。但是你不知道迭代器的类型;你只得到了容器的类型,而不是迭代器:
template <typename ContainerT>
void DoThings(ContainerT const& input)
{
/* ??? */ it = input.begin();
}
假设为了论证您可以解决该问题,并且您想取消对迭代器的引用。要存储结果,您需要知道是什么T
;但这又会导致同样的问题:
template <typename ContainerT>
void DoThings(ContainerT const& input)
{
/* ??? */ it = input.begin();
/* ??? */ firstElement = *it;
}
我们不知道T
,容器中包含的类型是什么;我们在这个函数模板中只有容器本身的类型。为了获得容器内的类型,我们需要容器来帮助我们一点,告诉我们它包含的类型是什么。容器类通过typedef
s 做到这一点。对于标准容器,这将iterator
用于迭代器类型和value_type
包含的值类型:
template <typename ContainerT>
void DoThings(ContainerT const& input)
{
// Container provides its iterator type via a typedef.
typename ContainerT::iterator it = input.begin();
// Container provides its contained type via a typedef.
typename ContainerT::value_type firstElement = *it;
}
即使在 C++11 中,您也可以使用以下方法解决上述示例auto
:
template <typename ContainerT>
void DoThings(ContainerT const& input)
{
// Make the compiler figure it out:
auto it = input.begin();
auto firstElement = *it;
}
有时您仍然希望能够为其他目的获取实际类型:
// Failure to compile: http://ideone.com/vxJ2IU
// Successful compile: http://ideone.com/b5fU3S
#include <vector>
#include <list>
#include <deque>
#include <type_traits>
#include <iostream>
template <typename ContainerT>
void DoThings(ContainerT const& input)
{
// DoThings only accepts integral containers:
static_assert(
std::is_integral<typename ContainerT::value_type>::value,
"DoThings requires that the contained type be integral");
// Make the compiler figure it out:
auto it = input.begin();
auto firstElement = *it;
std::cout << firstElement;
}
int main()
{
std::vector<int> abc;
abc.push_back(42);
std::list<long> def;
def.push_back(1729);
std::deque<short> queue;
queue.push_back(1234);
DoThings(abc);
DoThings(def);
DoThings(queue);
// Does not compile due to static assert:
std::vector<double> doubles;
doubles.push_back(3.14);
DoThings(doubles);
}