1

我已经快速编写了带模板元编程的reduce函数。我知道这是不完美的,我应该检查类型兼容,返回类型...使用具有可变参数函数的初始化列表

#include <iostream> 
#include <functional> 

template <typename Functor, typename T> 
T reduce(Functor f, T v) { 
    return v; 
} 

template<typename Functor, typename T1, typename... Ts> 
T1 reduce(Functor f, T1 t1, Ts... ts) { 
    return f(t1, reduce(f, ts...)); 
} 

int main() { 
    std::cout << reduce(std::plus<int>(), 1, 2, 3, 4, 5, 6, 7) << std::endl; 
    return 0; 
} 

的一点是,我希望写的东西像

std::cout << reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7}) << std::endl; 

或者如果可能的话

const int input[3] = {1, 2, 3}; 
std::cout << reduce(std::plus<int>(), input) << std::endl; 
+1

是什么问题?只需添加一个超载需要'std :: initializer_list '? –

+1

为什么不使用'std :: accumulate'? –

+0

@ Cheersandhth.-Alf:编译时间 –

回答

1

你并不需要一个可变参数模板:

#include <algorithm> 
#include <iostream> 
#include <iterator> 

namespace Detail { 
    template <typename Functor, typename List> 
    typename Functor::result_type reduce(Functor f, const List& list) { 
     using std::begin; 
     using std::end; 
     typename Functor::result_type result{}; 
     auto pos = begin(list); 
     if(pos != end(list)) { 
      result = *pos; 
      while(++pos != end(list)) 
       result = f(result, *pos); 
     } 
     return result; 
    } 
} // namespace Detail 

template <typename Functor, typename List> 
typename Functor::result_type reduce(Functor f, const List& list) { 
    return Detail::reduce(f, list); 
} 

template <typename Functor, typename T> 
typename Functor::result_type reduce(Functor f, std::initializer_list<T> list) { 
    return Detail::reduce(f, list); 
} 

int main() { 
    std::cout << reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7}) << std::endl; 
    const int input[3] = {1, 2, 3}; 
    std::cout << reduce(std::plus<int>(), input) << std::endl; 
} 
012使用 'constexpr'

A C++ 11(克++ 4.8.4)的变化:

#include <algorithm> 
#include <iostream> 
#include <iterator> 

// constexpr plus is C++14 
template<typename T> 
struct plus : public std::binary_function<T, T, T> 
{ 
    constexpr T operator()(const T& x, const T& y) const { return x + y; } 
}; 

// constexpr begin is C++14 
template<class T, std::size_t N> 
inline constexpr T* begin(T (&array)[N]) { return array; } 

// constexpr end is C++14 
template<class T, std::size_t N> 
inline constexpr T* end(T (&array)[N]) { return array + N; } 

template <typename Functor, typename Iterator> 
inline constexpr typename Functor::result_type 
reduce(
    const Functor& f, 
    const typename Functor::result_type& value, 
    Iterator first, 
    Iterator last) 
{ 
    return (first != last) 
     ? reduce(f, f(value, *first), first + 1, last) 
     : value; 
} 

template <typename Functor, typename T, std::size_t N> 
constexpr typename Functor::result_type reduce(const Functor& f, T (&array)[N]) { 
    // constexpr begin/end is C++14 
    // using std::begin; 
    // using std::end; 
    return reduce(f, typename Functor::result_type{}, begin(array), end(array)); 
} 

template <typename Functor, typename T> 
inline constexpr typename Functor::result_type reduce(
    const Functor& f, 
    std::initializer_list<T> list) 
{ 
    return reduce(f, typename Functor::result_type{}, list.begin(), list.end()); 
} 

int main() { 
    static constexpr int input[3] = {1, 2, 3}; 
    static_assert(28 == reduce(plus<int>(), {1, 2, 3, 4, 5, 6, 7}), "Failure"); 
    static_assert(6 == reduce(plus<int>(), input), "Failure"); 
} 
+0

其中'Detail :: reduce'在adl启用'begin'和'end'时会更通用一些。 – Pixelchemist

+0

@Pixelchemist我不明白,请澄清一下? –

+0

我需要在编译时评估它,如原始示例 –

1

http://ideone.com/nM8HH3

#include <iostream> 
#include <functional> 
#include <initializer_list> 

template<typename Functor, typename T, size_t N> 
T constexpr reduce(Functor f, T(&arr)[N]) { 
    typename std::remove_const<T>::type val = arr[0]; 
    for(auto i = std::begin(arr)+1; i != std::end(arr); ++i) val = f(val, *i); 
    return val; 
} 

template<typename Functor, typename T> 
T constexpr reduce(Functor f, std::initializer_list<T> il) { 
    T val = *il.begin(); 
    for(auto i = il.begin()+1; i != il.end(); ++i) val = f(val, *i); 
    return val; 
} 

template<typename Functor, typename T, typename... Ts> 
T constexpr reduce(Functor f, T t1, Ts... ts) { 
    return f(t1, reduce(f, std::initializer_list<T>({ts...}))); 
} 

template<int value> 
void print_constexpr() { std::cout << value << std::endl; } 

int main() { 
    // run-time or compile-time 
    std::cout << reduce(std::plus<int>(), 1, 2, 3, 4, 5, 6, 7) << std::endl; // 28 
    std::cout << reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7}) << std::endl;// 28 
    const int input[3] = {1, 2, 3}; // 6 
    std::cout << reduce(std::plus<int>(), input) << std::endl; 

    // compile-time 
    print_constexpr< reduce(std::plus<int>(), 1, 2, 3, 4, 5, 6, 7) >();  // 28 
    print_constexpr< reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7}) >(); // 28 
    constexpr int input_constexpr[3] = {1, 2, 3}; // 6 
    print_constexpr< reduce(std::plus<int>(), input_constexpr) >(); // 6 

    return 0; 
} 

输出:

28 
28 
6 
28 
28 
6 

可以在编译时使用以下任何一种:

  • reduce(std::plus<int>(), 1, 2, 3, 4, 5, 6, 7)
  • reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7})
  • reduce(std::plus<int>(), input)

对于任何constexpr -functors。

相关问题