Сбой помощника по сумме для классов

У меня написано следующее 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;
}

Почему я не могу сделать сумму (а, б, в)? Когда у меня + B + C работает, как продемонстрировать.

Это дает ошибку компиляции, когда я передаю объекты, но не когда я передаю примитивные типы

Я не могу понять вывод ошибки / замена аргумента шаблона ошибки .. как?

1

Решение

Вот вариант вариационной 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 переопределения потребовали небольшой настройки.

Внедрение foldl без 3 или более переопределений немного сложнее.

Вот еще один ответ, где они обсуждают лучшие способы обойти эту проблему:

Как реализовать сворачивание с помощью шаблонов

2

Другие решения

Это мой плохой (из предыдущего ответа) вы должны добавить еще одну специализацию шаблона в верхней части для одного элемента. Иначе sum(1,2,3) не найдет совпадения, потому что первые два аргумента будут совпадать с переменным, а другой ожидает два аргумента. Остался только один.

template <typename T>
T sum(const T& v) {
return v;
}

Здесь опять другая проблема — ваш оператор + выходит без возврата чего-либо. Который Неопределенное поведение. И если вы определите его как член, он должен быть постоянным.

struct A {
int x;
A(const int a) : x(a) { std::cout<<x<<std::endl; };
A operator+(const A &a1) const
{
return A(a1.x + x);
}
};

Итак, ваша полная программа должна выглядеть так

template <typename T>
T sum(const T& v) {
return v;
}

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

struct A {
int x;
A(const int a) : x(a) { };
A operator+(const A &a1) const { return A(a1.x + x); }
};

int main () {
std::cout<<"sum of 1,2.2,3,4 is : ";
auto ans = sum(1,2.2,3,4);
cout << ans;A a(1); A b(2); A c(3);
a+b+c;
auto ans2 = sum(a,b,c);
std::cout<<std::endl<<"sum of A(1),A(2),A(3) is : ";
std::cout<<ans2.x<<std::endl;
return 0;
}

стандартный вывод

sum of 1,2.2,3,4 is : 10.2
sum of A(1),A(2),A(3) is : 6
2

Вот правильная сумма

#include <iostream>

namespace cs540 {
template <typename T>
const T & sum(const T & v) {
return v;
}

template <typename T, typename T2, typename ... Ts>
T sum(const T & v, const T2 & w, const Ts & ... params) {
return sum(w+v,params...);
}
}

int main() {
using namespace cs540;
using namespace std;
cout << sum(1.1,2,3,4,6,8,9,1.1) << endl;
}

Вам также нужно пометить ваш оператор метода + как const

1
По вопросам рекламы [email protected]