在今年的主题演讲中,Going Native The Essence of C++(转到40:30)Bjarne Stroustrup给出了以下代码示例:
template<typename C, typename V>
vector<Value_type<C>*> find_all(C& cont, V v)
{
vector<Value_type<C>*> res;
for (auto& x : cont)
if (x == v)
res.push_back(&x)
return res;
}
此函数用于查找容器中所有值的值 并返回指向找到的元素的指针。视频中的示例:
string m{"Mary had a little lamb"};
for (const auto p: find_all(m,'a')) // p is a char*
if (*p != 'a')
cerr << "string bug!\n";
我的问题是 Value_Type<C>*
。标准中是否有这样的东西
图书馆?我寻找它并没有找到它。如果它不在std中,怎么能实现呢?
答案 0 :(得分:9)
我在标准中并不知道这一点,但实施起来并不难:
template <class C>
struct value_type
{
typedef typename C::value_type type;
};
template <class T, int N>
struct value_type<T[N]>
{
typedef T type;
};
template <class T>
struct value_type<T*>
{
typedef T type;
};
现在您可以使用typename value_type<C>::type
来访问容器包含的类型。如果你有自己想要使用的容器,但它没有value_type
typedef(无论出于何种原因你都无法改变它),那么你也可以简单地为这个容器专门化这个结构。 / p>
要避免typename ...::type
你可以这样做:
template <class C>
using Value_Type = typedef value_type<C>::type;
现在你只需在任何地方使用Value_Type<C>
。
修改强>
正如stefan在很快的回答中建议的那样,您可以使用std::begin
更轻松地完成此操作,这是可以的,因为您使用/创建的任何容器都希望无论如何都可以调用std::begin
和std::end
:
template <class C>
using Value_Type = typename std::remove_reference<
decltype(*std::begin(std::declval<
typename std::add_lvalue_reference<C>::type>()))>::type;
这更加简洁,尽管读起来有点密集。它仍然比第一个选项更好,这将需要更少的自定义容器类型的样板代码。
答案 1 :(得分:3)
Value_type<C>
只是C::value_type
的typedef。据我所知,目前标准库中没有这样的typedef,但您可以自己定义:
template <class T>
using Value_type = typename T::value_type;
template<typename C, typename V>
std::vector<Value_type<C>*> find_all(C& cont, V v)
{
std::vector<Value_type<C>*> res;
for (auto& x : cont)
if (x == v)
res.push_back(&x);
return res;
}
int main()
{
std::vector<int> v{1, 2, 3, 3, 5};
for(const auto x: find_all(v, 3))
{
std::cout << *x << std::endl;
}
}
但是,正如@stefan建议的那样,这只适用于标准容器。您可以使用std::begin
函数(也为数组定义)检索基础类型,它是如何在@ GuyGreer的答案中实现的