4
\$\begingroup\$

I made a simple script to implement basic mathematics operations by using variadic functions. I would like to know if my implementation is correct.

The code only works for Visual C++ compiler Nov 2013 CTP (CTP_Nov2013).

#include <iostream>
#include <string>
#include <exception>
using namespace std;
template <typename T>
T add(T&& item = T())
{
 return forward<T>(item);
}
template <typename T, typename ... Types>
auto add(T&& first, Types&& ... rest)
 -> decltype(first + add(forward<Types>(rest)...))
{
 return forward<T>(first) + add(forward<Types>(rest)...);
}
template <typename T>
T sub(T&& i = T())
{
 return forward<T>(i);
}
template <typename T, typename ... Types>
auto sub(T&& first, Types&& ... rest)
-> decltype(forward<T>(first) - sub(forward<Types>(rest)...))
{
 return forward<T>(first) - sub(forward<Types>(rest)...);
}
template <typename T>
T multiple(T&& i = T())
{
 return forward<T>(i);
}
template <typename T, typename ... Types>
auto multiple(T&& first, Types&& ... rest)
-> decltype(forward<T>(first) * multiple(std::forward<Types>(rest)...))
{
 return forward<T>(first) * multiple(forward<Types>(rest)...);
}
template <typename T>
T divide(T&& item = T())
{
 return forward<T>(item);
}
template <typename T, typename ... Types>
auto divide(T&& first, Types&& ... rest)
 -> decltype(forward<T>(first) / divide(forward<Types>(rest)...))
{
 if (divide(forward<Types>(rest)...) == 0)
 throw "Opps divided by Zero";
 return forward<T>(first) / divide(forward<Types>(rest)...);
}
template<typename... Types>
void termnate(Types&&...)
{
 std::cout << '\n';
}
template<typename... Types>
void result(Types&&... t)
{
 termnate{ ([&]{ std::cout << forward<Types>(t) << ' '; }(), 1)... };
}
int main()
{
 result( add(1, 2.5, 3, 4, 5), " = ", "1 + 2,5 + 3 + 4 + 5");
 result(sub(sub(sub(sub(1, 2.5), 3), 4), 5), " = ", "1 - 2.5 - 3 - 4 - 5"); // OK = -13.5
 result(multiple(1, 2.5, 3, 4, 5), " = ", "1 x 2.5 x 3 x 4 x 5");
 result(divide(divide(divide(divide(1, 2.5), 3), 4.5), 5), " = ", "1 / 2.5 / 3 / 4 / 5"); // OK = .005926
 cout << add("\nTest ", "template: ", string("PASS\n"));
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Dec 10, 2014 at 6:33
\$\endgroup\$
10
  • 2
    \$\begingroup\$ Subtraction and division are not associative, so I am not sure how to define correctness of their variadic versions. Obviously, division by 0 returning 1 is wrong. \$\endgroup\$ Commented Dec 10, 2014 at 6:43
  • \$\begingroup\$ @vnp ... yes, i was testing static_assert() but it won't be, i dunno why \$\endgroup\$ Commented Dec 10, 2014 at 6:50
  • \$\begingroup\$ I'm fairly certain that you should be using forward when you pass on the && move references in the recursive calls. \$\endgroup\$ Commented Dec 10, 2014 at 13:31
  • 1
    \$\begingroup\$ Don't forget to explicitly pass the template type (e.g.: std::forward<T>(x)), it can't figure out the type by itself otherwise. \$\endgroup\$ Commented Dec 10, 2014 at 13:36
  • 1
    \$\begingroup\$ @glampert .. thanks that really deserve tobe an answer \$\endgroup\$ Commented Dec 10, 2014 at 13:53

1 Answer 1

2
\$\begingroup\$

When passing around move references, the recommended is to forward the parameters to ensure that the move reference is preserved:

template <typename T, typename ... Types>
auto add(T&& first, Types&& ... rest) 
 -> decltype(first + add(std::forward<Types>(rest)...))
{
 return first + add(std::forward<Types>(rest)...);
}

Note that you have to explicitly provide the template type to std::forward(). It would deduce the wrong type otherwise.

answered Dec 10, 2014 at 14:11
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.