如何测试模板参数是否是一对关联容器?

发布于 2024-08-21 15:14:36 字数 381 浏览 3 评论 0原文

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

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

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

但是,对于成对关联容器(std::map),

return c.begin()->second;

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

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

Let's imagine I want to make a templated function that returns the first element of any stl container. The general way would be :

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

This works for vectors, lists, deques, sets and so on.

However, for pair associative containers (std::map), if would like to have

return c.begin()->second;

How could I test (in the function or with template specialization) if I have an pair associative container ?

STL container seem to have no traits attached to it. Is it possible to check if it has a ::key_type ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

汹涌人海 2024-08-28 15:14:36

您可以很容易地做到这一点:

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()); }

但我应该注意,我可能会添加一个测试来查看容器是否为空...因为如果容器为空,您正在执行未定义的行为。

运动中:

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 ;)

You can do quite easily:

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()); }

I should note though, that I would probably add a test to see if the container is empty... Because if the container is empty, you're on for undefined behavior.

In movement:

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

Example shamelessly taken from litb ;)

似梦非梦 2024-08-28 15:14:36

这个有效:(

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

This one works:

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);
}

(outputs 4243)

单身狗的梦 2024-08-28 15:14:36

使用模板函数的特化:

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;
}

Use specialization of template function:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文