//a class template to do something to STL container
template<typename T/*should be a STL container*/,typename Ele/*the type of element*/>
struct foo{
T a_container_with_an_element(){
T con;
Ele e;
con.push_back(++++e);
return con;
}
正如您所看到的,将元素的类型放入模板参数是非常愚蠢的,因为它已经包含在容器的类型中。
那么,从T中获取元素的类型是否有任何魔力?
很多Thx: - )
答案 0 :(得分:5)
如果容器是标准库容器,则元素的名称是容器的嵌入名称,如下所示:
typedef typename T::value_type type;
标准容器中有一些标准名称(例如,请参阅vector on cppreference)和C++ standard§23.2。
X::value_type
X::reference
X::const_reference
X::iterator
X::const_iterator
X::difference_type
X::size_type
答案 1 :(得分:3)
每个&#34; 容器&#34;在标准库中,尝试遵守Container
concept。这个概念要求给定容器T
:
T::value_type
是容器元素的类型T::reference
是容器元素的引用类型T::const_reference
是容器元素的常量引用类型在您的具体示例中,您可以通过以下方式提取元素类型:
template<typename Container>
struct foo {
Container a_container_with_an_element(){
Container con;
typename Container::value_type e;
con.push_back(++++e);
return con;
}
答案 2 :(得分:0)
如果T
应该是STL容器,则可以使用template-template参数。它必须是一个支持push_back()
的容器,我们将结合STL容器包含第二个&#34;分配器&#34;参数。
在这种情况下,您可以使用
template< template<typename, typename> class Con,
typename Ele, typename Alloc = std::allocator<Ele> >
struct foo
{
typedef Con<Ele, Alloc> container_type;
typedef Ele value_type;
container_type a_container_with_an_element()
{
container_type con;
value_type e;
con.push_back( e ); // or modify e first but not ++++e
return con;
}
};
然后你的代码会
foo< std::vector, int > myfoo;
std::vector<int> myvec = myfoo.a_container_with_an_element();
如果您只想要一个模板参数
template< typename Con >
struct foo
{
typedef typename Con::value_type value_type;
Con a_container_with_an_element()
{
Con con;
value_type e;
con.push_back( e ); // or modify e first but not ++++e
return con;
}
};
和用法:
foo<std::vector<int> > myfoo;
std::vector<int> myvec = myfoo.a_container_with_an_element();
请注意,在此示例中,您还可以执行foo<std::vector<int> >::Ele
以获取元素类型。您也可以为容器类型创建typedef
。经常用在模板中。 (当模板不完全合格时,您需要typename
。因此foo<std::vector<int>>
完全合格,并且不需要它。
答案 3 :(得分:0)
在您知道T是STL容器的特殊情况下,Naill的答案是正确的,请使用容器中的嵌套类型。
如果你想要更通用的&#34;我知道我得到的模板为T,我想要该模板的第一个参数的类型&#34;例如,您可以通过模板专业化获取类型:
template<typename T>
struct MyFirstElement;
template<template<typename...> class T_Container, typename T_Type, typename... Ts>
struct MyFirstElement<T_Container<T_Type,Ts...>>{
using Type = T_Type;
};
//unit test
using MustBeInt = typename MyFirstElement<std::vector<int>>::Type;
using MustBeLong = typename MyFirstElement<std::map<long,float>>::Type;
static_assert(std::is_same<MustBeInt,int>::value,"");
static_assert(std::is_same<MustBeLong,long>::value,"");
//this works too even though its not an STL container
template<typename T, typename U, typename Z>
struct MyCrazyContainer{};
static_assert(std::is_same<typename MyFirstElement<MyCrazyContainer<bool,long,float>>::Type,bool>::value,"");
这是一个实例:http://ideone.com/OxhSOc
正如Jarod42指出的那样,这只适用于常规&#34;模板。即只有类型作为参数。 std :: array例如呼吸这个因为它有一个int作为第二个参数。