Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

More than one round bracket in function call?

I have an exercise where I need to write a function. Function scheme look like

auto add(int a){
}

I need to be able to call this function with many brackets:

add(1)(2)(3); // 6
add(1)(2)(3)(4); // 10
add(1)(2)(3)(4)(5); // 15

But I can not figure out which C++ feature I should use in this case. I heard that I should use functors but I don't know if this is the best idea in this case.

like image 786
jerry Avatar asked May 24 '17 07:05

jerry


1 Answers

You can do it by having add return a functor, i.e., an object that implements operator(). You can write a templated version that will let the compiler deduce the type. Try it here.

template <class T>
struct adder 
{
    T val;

    adder(T a) : val(a) {}

    template <class T2>
    auto operator()(T2 a) -> adder<decltype(val + a)> { return val + a; }

    operator T() const { return val; }
};

template <class T>
adder<T> add(T a)
{
    return a;
}

Example

In this example, T will ultimately resolve to double:

std::cout << add(1)(2.5)(3.1f)(4) << std::endl;
// T is int -----^
// T is double ------^
// T is still double -----^
// T is still double ----------^

Here is another example where T will resolve to double:

std::cout << add(1)(2.5f)(3.1)(4) << std::endl;
// T is int -----^
// T is float -------^
// T is double ------------^
// T is still double ----------^

Explicit Constructor

If you want the constructor of adder to be explicit you also have to change the return statements slightly.

template <class T>
struct adder 
{
    T val;

    explicit adder(T a) : val(a) {}

    template <class T2>
    auto operator()(T2 a) -> adder<decltype(val + a)>
    {
        return adder<decltype(val + a)>(val + a);
    }

    operator T() const { return val; }
};

template <class T>
adder<T> add(T a)
{
    return adder<T>(a);
}
like image 98
Jonas Avatar answered Sep 18 '22 09:09

Jonas