从模板范围获取类型

时间:2015-02-26 09:27:51

标签: c++ templates c++11 visual-studio-2013 stl

TL; DR

R作为模板参数,Rsome_container<T>T[],如何推断T

可能的实施是std::iterator_traits<decltype(std::begin(r))>::value_type,寻找不那么详细的东西。

阐述

我正在尝试围绕std::accumulate算法实现一个包装器,所以不要输入这个:

std::accumulate(v.begin(), v.end(), 0, [](int x, int y) { return x * y; });

用户只需写下:

my::accumulate(v, [](int x, int y) { return x * y; });

基本上,给定一个实体和一个操作,my::accumulate旨在使用以下参数调用std::accumulate

    来自给定实体的
  1. std::begin()
  2. 来自给定实体的
  3. std::end()
  4. 默认构造的值作为起点
  5. 给定操作
  6. 我使用免费的beginend函数来允许函数在内置数组上工作。因此,传递的实体是范围。这是我的实施:

    template<class R, typename F>
    auto accumulate(const R& r, F&& f) -> 
      typename std::iterator_traits<decltype(std::begin(r))>::value_type
    {
      using T = std::iterator_traits<decltype(std::begin(r))>::value_type;
      return std::accumulate(std::begin(r), std::end(r), T{}, std::forward<F>(f));
    }
    

    工作正常。唯一困扰我的是丑陋的std::iterator_traits<decltype(std::begin(r))>::value_type建筑。 是否有更好的方法从范围中获取类型?请注意,R不必是容器,因此我无法使用R::value_type

    请注意,我使用的是Visual Studio 2013,因此我可以使用大部分C ++ 11和一些C ++ 14。

    PS。有关实施的任何其他意见?有任何缺点或影响吗?

1 个答案:

答案 0 :(得分:1)

您可以使用typename std::remove_reference_t<decltype(*std::begin(r))>来保存一些按键,但效果不是很好。

我想您要实现的算法不仅仅是accumulate,在这种情况下,您可以为元素类型创建别名:

template<typename T>
using value_type = typename std::iterator_traits<decltype(std::begin(T{}))>::value_type;

template<class R, typename F>
value_type<R> accumulate(const R& r, F&& f) 
{
  return std::accumulate(std::begin(r), std::end(r), value_type<R>{}, std::forward<F>(f));
}

否则,您可以使用占位符返回类型来避免重复:

template<class R, typename F>
auto accumulate(const R& r, F&& f) 
{
  using T = typename std::iterator_traits<decltype(std::begin(r))>::value_type;
  return std::accumulate(std::begin(r), std::end(r), T{}, std::forward<F>(f));
}