c++ - Sum 帮助程序无法上课

标签 c++ templates c++11 variadic-templates g++-4.7

我写了以下 sumhelper:

template <typename T1, typename T2>
auto sum(const T1& v1, const T2& v2) -> decltype( v1 + v2) {
    return v1 + v2;
}

template <typename T1, typename T2, typename... Ts>
auto sum(const T1& v1, const T2& v2, const Ts&... rest) -> decltype( v1 + v2 + sum(rest...) ) {
    return v1 + v2 + sum(rest... );
}

这是CPP文件

#include <iostream>
#include <type_traits>
#include "Sum.hpp" 

struct A {
    int x;

    A(const int a) : x(a) { std::cout<<x<<std::endl; };

    A &operator+(const A &tmp) const {
        std::cout<<" + "<<tmp.x<<") ";
    };
};

int main () {
    std::cout<<"sum of 1,2,3,4 is : ";

    auto ans = sum(1,2.2,3,4);

    A a(1);
    A b(2);
    A c(3);

    std::cout<<a.x;
    a+b+c;

    sum(a,b,c); //Here is syntax error

    std::cout<<ans<<std::endl;
    return 0;
}

为什么我做不到 sum(a,b,c) ?当我让 a+b+c 像演示一样工作时。

当我传递对象时会出现编译错误,但当我传递原始类型时不会出现

我无法理解错误模板参数推导/替换失败..怎么办?

最佳答案

这里是可变参数 apply_binop 的一个变体,它将任意操作作为第一个参数,以及一个 sum 包装器,它传递一个二进制 add 到它。 apply_binop 更好(也更清楚)被称为 foldr 我相信:

#include <utility>
#include <iostream>

#define RETURNS(x) ->decltype(x) { return (x); }

struct add {
  template<typename T, typename U>
  auto operator()( T&& t, U&& u ) const
    RETURNS( std::forward<T>(t)+std::forward<U>(u) )
};


template<typename Op, typename T0>
auto apply_binop( Op&& op, T0&& t0 )
  RETURNS(std::forward<T0>(t0))

template<typename Op, typename T0, typename T1, typename... Ts>
auto apply_binop( Op&& op, T0&& t0, T1&& t1, Ts&&... ts )
  RETURNS(
    op(
      std::forward<T0>(t0),
      apply_binop(op, std::forward<T1>(t1), std::forward<Ts>(ts)...)
    )
  )

template<typename... Ts>
auto sum( Ts&&... ts )
  RETURNS( apply_binop( add(), std::forward<Ts>(ts)... ) )

int main() {
  std::cout << sum(1,2,3,4,5) << "\n";
  std::cout << sum(1) << "\n";
  std::cout << sum(1,2) << "\n";
  std::cout << sum(1,2,3) << "\n";
  std::cout << sum(1,2,3,4) << "\n";
  std::cout << sum(1,2,3,4.7723) << "\n";
}

它是 foldr 因为它将二元运算应用于最右边的两个,然后获取该结果并将其应用于倒数第三个,等等。 foldl 做同样的开始从左边开始。

RETURNS 弥补了 C++ 无法推导单行函数的返回类型的问题(我相信这将在 C++17 中修复)。让 gcc 4.7.2 接受上面只有两个 apply_binop 覆盖需要一些调整。

在没有 3 个或更多覆盖的情况下实现 foldl 有点棘手。

这是另一个答案,他们讨论了解决此问题的更好方法:

How to implement folding with variadic templates

关于c++ - Sum 帮助程序无法上课,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16493378/

相关文章:

c++ - 此代码示例中使用了哪种模板特化?

c++ - STL std::map 动态排序

c++ - 具有不同模板的派生类对象的 vector

C++ - 如何将元素从 std::priority_queue 复制到 std::vector

c++ - Qt 记住上次打开的文件夹

c++ - 错误 C3867 多线程 C++

c++ - for_each 不返回( bool )值

c++ - 关于C++0x中右值的问题

c++ - 模板模板参数 - 类型/值不匹配错误

c++ - 为什么 std::function 不能接受推导类型作为其模板参数?