容器模板参数的Value_type

gui*_*ini 5 c++ std

在今年的主题演讲中,Going Native 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;
}
Run Code Online (Sandbox Code Playgroud)

此函数用于查找容器中所有值的值,并返回指向找到的元素的指针.视频中的示例:

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"; 
Run Code Online (Sandbox Code Playgroud)

我的问题是关于Value_Type<C>*.标准库中有这样的东西吗?我寻找它并没有找到它.如果它不在std中,怎么能实现呢?

Sir*_*Guy 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;
    };
Run Code Online (Sandbox Code Playgroud)

现在您可以typename value_type<C>::type用来访问容器包含的类型.如果您有自己想要使用的容器,但它没有value_typetypedef(无论出于何种原因您无法更改它),那么您也可以简单地为该容器专门化这个结构.

为了避免typename ...::type你可以这样做:

    template <class C>
    using Value_Type = typedef value_type<C>::type;
Run Code Online (Sandbox Code Playgroud)

现在你只是Value_Type<C>到处使用.

编辑
正如stefan在很快的回答中建议的那样,你可以更轻松地做到这一点std::begin,因为你使用/创建的任何容器都希望能够打电话std::beginstd::end无论如何:

    template <class C>
    using Value_Type = typename std::remove_reference<
        decltype(*std::begin(std::declval<
            typename std::add_lvalue_reference<C>::type>()))>::type;
Run Code Online (Sandbox Code Playgroud)

这更加简洁,虽然阅读时有点密集.它仍然比第一个选项更好,这将需要更少的自定义容器类型的样板代码.

  • 稍有不妥:在你的decltype东西周围添加`typename std :: remove_reference <`...`> :: type` ;-)演示:http://ideone.com/bCF0qz (2认同)