HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Simple mathematical operations (add, sub, mul, div) in C++11 template

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
simpleoperationstemplatemathematicaldivsubmuladd

Problem

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 
#include 
#include 
using namespace std;

template 
T add(T&& item = T())
{
    return forward(item);
}

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

template 
T sub(T&& i = T())
{
    return forward(i);
}

template 
auto sub(T&& first, Types&& ... rest)
-> decltype(forward(first) - sub(forward(rest)...))
{
    return forward(first) - sub(forward(rest)...);
}

template 
T multiple(T&& i = T())
{
    return forward(i);
}

template 
auto multiple(T&& first, Types&& ... rest)
-> decltype(forward(first) * multiple(std::forward(rest)...))
{
    return forward(first) * multiple(forward(rest)...);
}

template 
T divide(T&& item = T())
{
    return forward(item);
}

template 
auto divide(T&& first, Types&& ... rest)
    -> decltype(forward(first) / divide(forward(rest)...))
{
    if (divide(forward(rest)...) == 0)
        throw "Opps divided by Zero";
    return forward(first) / divide(forward(rest)...);
}

template
void termnate(Types&&...)
{
    std::cout 
void result(Types&&... t)
{
    termnate{ ([&]{ std::cout (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"));
}

Solution

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

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


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

Code Snippets

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

Context

StackExchange Code Review Q#72214, answer score: 2

Revisions (0)

No revisions yet.