【问题标题】:How to test if template parameter is a pair associative container?如何测试模板参数是否是一对关联容器?
【发布时间】:2010-02-18 14:17:18
【问题描述】:

假设我想创建一个模板函数,它返回任何 stl 容器的第一个元素。一般的方法是:

template<typename Container>
Container::value_type first(Container c){
    return *(c.begin());
}

这适用于向量、列表、双端队列、集合等。

但是,对于配对关联容器(std::map),如果想拥有

return c.begin()->second;

如果我有一对关联容器,我该如何测试(在函数中或使用模板特化)?

STL 容器似乎没有附加任何特征。是否可以检查它是否有 ::key_type ?

【问题讨论】:

    标签: c++ templates stl


    【解决方案1】:

    你可以很容易做到:

    namespace result_of // pillaged from Boost ;)
    {
      template <class Value>
      struct extract { typedef Value type; };
    
      template <class First, class Second>
      struct extract < std::pair<First,Second> > { typedef Second type; };
    }
    
    template <class Value>
    Value extract(Value v) { return v; }
    
    template <class First, class Second>
    Second extract(std::pair<First,Second> pair) { return pair.second; }
    
    template <class Container>
    typename result_of::extract< typename Container::value_type >::type
    first(const Container& c) { return extract(*c.begin()); }
    

    但我应该注意,我可能会添加一个测试来查看容器是否为 empty...因为如果容器是 empty,那么您将面临未定义的行为。

    运动中:

    int main(int argc, char* argv[])
    {
      std::vector<int> vec(1, 42);
      std::map<int,int> m; m[0] = 43;
      std::cout << first(vec) << " " << first(m) << std::endl;
    }
    
    // outputs
    // 42 43
    

    无耻取自litb的例子;)

    【讨论】:

    • 不错的答案。要让它编译,';'在结构的末尾缺少并且 .front() 不适用于所有内容
    • 哎呀,你的回答有点太快了:我已经添加了缺失的 ; 并用取消引用的 begin 替换了 front :)
    【解决方案2】:

    这个有效:

    template<typename T>
    struct tovoid {
      typedef void type;
    };
    
    template<typename T, typename = void>
    struct value_type {
      typedef typename T::value_type type;
      static type get(T const& t) {
        return *t.begin();
      }
    };
    
    template<typename T>
    struct value_type<T, typename tovoid<typename T::mapped_type>::type> {
      typedef typename T::mapped_type type;
      static type get(T const& t) {
        return t.begin()->second;
      }
    };
    
    template<typename Container>
    typename value_type<Container>::type first(Container const& c){
        return value_type<Container>::get(c);
    }
    
    int main() {
      std::map<int, int> m; m[0] = 42; std::cout << first(m);
      std::vector<int> a(1, 43); std::cout << first(a);
    }
    

    (输出4243

    【讨论】:

      【解决方案3】:

      使用模板函数的特化:

      template<typename Container>
      typename Container::value_type first(typename Container c)
      {
          return *(c.begin());
      }
      
      
      template<typename K, typename V>
      typename V first(std::map<K,V> & c)
      {
          return c.begin()->second;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-07
        • 1970-01-01
        • 1970-01-01
        • 2019-09-29
        • 2016-12-02
        • 2019-07-27
        相关资源
        最近更新 更多