5

在今年 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>*. 标准库中有这样的东西吗?我寻找它并没有找到它。如果它不在标准中,如何实现?

4

2 回答 2

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_typetypedef(并且无论出于何种原因,您都无法更改它),那么您也可以简单地为该容器专门化这个结构。

为了避免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;

这要简洁得多,尽管阅读起来有点密集。它仍然比第一个选项更好,这将需要更少的自定义容器类型的样板代码。

于 2013-11-12T14:17:53.673 回答
3

Value_type<C>只是C::value_type. 据我所知,标准库中没有这样的 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 的答案中实现的

于 2013-11-12T14:15:43.957 回答