Overloading () operator

I am pretty sure this is a beginner question. However, all my google searches failed me. So, here I am.

To begin, let's say, I have a few function like,

1
2
3
4
5
6
7
8
  template<typename T>
  T foo1(T& a){return a+1;}

  template<typename T>
  T foo2(T& a){return a-2;}

  template<typename T>
  T foo3(T& a){return a*3;}


Now, I want to overload the function call operator for vector. So, something similar to,

1
2
3
4
5
  template<class T>
  std::vector<T> operator()(std::vector<T>& vec)
  {
    for(auto& n:vec){//I don't know what to do here}
  }


I can do it for a specific function. But what I want to do is that overload the operator in general such that if the argument is vector, it will call the (arbitrary) function for each element. So that I can call like this,

1
2
3
4
  std::vector<int> a = {1,2,3,4};
  std::vector<int> b = foo1(a);
  std::vector<int> c = foo2(a);
  std::vector<int> d = foo3(a);


Is this possible? How? what should be overload function's statement?

Thank you for your time.
Last edited on
You are trying to overload std::vector's constructor, there are already a multitude of overloads.
https://en.cppreference.com/w/cpp/container/vector/vector
@George P, can you give an example of how the constructor can be used for this?
 
std::vector<int> b = foo1(a);


Preferably, I don't want to use std::transform.
Did you not look at the code example at the link I posted?

Where did std::transform come from? There is no mention of it.
@George P, Sorry for the misunderstanding. I checked the constructor examples but none of them fits what I need.
std::transform is not in that link. I meant that, what I want to do can be done using transform but I would prefer not for certain reason.
I needed some serious coffeeage, what you are trying to do wasn't and still isn't all that clear through some terminology misunderstanding.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <vector>

template<typename T>
std::vector<T> add_one(std::vector<T> vec)
{
   for (auto& itr : vec)
   {
      itr++;
   }

   return vec;
}

int main()
{
   std::vector<int> ivec { 1, 2, 3, 4, 5 };

   std::vector<int> ivec1 { add_one(ivec) };

   for (const auto& itr : ivec) { std::cout << itr << ' '; }
   std::cout << '\n';

   for (const auto& itr : ivec1) { std::cout << itr << ' '; }
   std::cout << "\n\n";

   std::vector dvec {1.2, 3.4, 5.6, 7.8 };

   std::vector dvec1 { add_one(dvec) };

   for (const auto& itr : dvec) { std::cout << itr << ' '; }
   std::cout << '\n';

   for (const auto& itr : dvec1) { std::cout << itr << ' '; }
   std::cout << '\n';

}
1 2 3 4 5
2 3 4 5 6

1.2 3.4 5.6 7.8
2.2 4.4 6.6 8.8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <vector>
#include <concepts>

// overload for integral types
template < std::integral T > static T foo( const T& v, int n = 1 ) noexcept { return v+n ; }

// overload for vectors of integral types
template < std::integral T > static std::vector<T> foo( const std::vector<T>& vec, int n = 1 )
{ auto result = vec ; for( auto& v : result ) v = foo(v,n) ; return result ; }

int main()
{
    const std::vector<int> vec { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } ;

    const auto vec_p1 = foo(vec) ; // add 1 to each element
    for( int v : vec_p1 ) std::cout << v << ' ' ; // 1 2 3 4 5 6 7 8 9 10
    std::cout << '\n' ;

    const auto vec_p100 = foo(vec,100) ; // add 100 to each element
    for( int v : vec_p100 ) std::cout << v << ' ' ; // 100 101 102 103 104 105 106 107 108 109
    std::cout << '\n' ;

    const auto vec_m20 = foo(vec,-20) ; // subtract 20 from each element
    for( int v : vec_m20 ) std::cout << v << ' ' ; // -20 -19 -18 -17 -16 -15 -14 -13 -12 -11
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/fe76df126517d1d7
Concepts is C++20 new to me, still working at it. Thanks for the example, JLBorges. :)
@George P, perhaps my explanation is bad. The functions themselves don't take vector. The functions only take one single argument and returns a single. So, the function call should be, double x = foo1(3.0);. I want to overload the function call operator such that when the function is called with a vector instead, the operator overload function will call the function foo1 for every element of the vector. Now, the function can be any arbitrary function. Not a specific function.
@JLBorges, I am trying to overload the function call operator. Not the functions. Overloading each function individually would defeat the purpose here.
Don't know what you are driving at.
Are you looking for something like this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <vector>
#include <concepts>

struct caller_t
{
    // overload the call operator for vectors of integral types
    // (apply the function FN to each element of the vector)
    template < std::integral T, typename FN >
    std::vector<T> operator() ( const std::vector<T>& vec, const FN& fn ) const
    { auto result = vec ; for( auto& v : result ) v = fn(v) ; return result ; }
};

int main()
{
    const std::vector<int> vec { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } ;
    const caller_t caller ; // function object

    const auto vec_p1 = caller( vec, []( int v ) { return v+1 ; } ) ; // call operator: add 1 to each element
    for( int v : vec_p1 ) std::cout << v << ' ' ; // 1 2 3 4 5 6 7 8 9 10
    std::cout << '\n' ;

    const auto vec_p100 = caller( vec, []( int v ) { return v-20 ; } ) ;  // call operator: subtract 20 from each element
    for( int v : vec_p100 ) std::cout << v << ' ' ; // -20 -19 -18 -17 -16 -15 -14 -13 -12 -11
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/d16150c581d42569
You keep changing the requirements, as well as the examples of what you want. Your explanations are all over the place.

First you want functions that work and return a std::vector. Yet now you want functions that are passed a vector and return a double. M'ok, so what is supposed to happen to the vector's elements to return that singular double?

What EXACTLY are you trying to do? Explain THAT is more detail. LOTS more detail.

You're in better hands with JLBorges. I'm outta here.
Last edited on
Did you want fmap? This is a function that takes a function on elements and returns a new function that works with vectors of elements. Although there is somewhat more to it than this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <utility>
#include <type_traits>
#include <iostream>

// TODO: add more overloads for other "vector-like" types as needed
#include <vector>
template <typename F, typename T> 
  auto fmap_impl(F f, std::vector<T> const& xs)
  { 
    std::vector<std::decay_t<decltype(f(std::declval<T const&>()))>> result;
    for (auto const& x: xs) 
      result.push_back(f(x));
    return result;
  }

template <typename F> 
  class fmap_result_fn 
  {
    F f;
  public:
    explicit fmap_result_fn(F f): f(f) {}
    template <typename Z>
      constexpr auto operator()(Z&& z) const
      { return fmap_impl(f, std::forward<Z>(z)); }
  };

inline constexpr struct fmap_fn 
{  
  template <typename F> 
    constexpr auto operator()(F f) const { return fmap_result_fn(f); }
  template <typename F, typename T> 
    constexpr auto operator()(F f, T&& t) const 
    { return fmap_result_fn(f)(std::forward<T>(t)); }
} fmap;

int main()
{
  std::vector as = { 1, 2, 3, 4 };
  std::vector bs = fmap([](auto x) { return x / 2; }, as);
  std::vector cs = fmap([](auto x) { return x / 2.0; })(as);
  auto x2 = fmap([](auto x){ return x * 2.0; });
  std::vector ds = x2(as);
  
  for (auto a: as) std::cout << std::fixed << a << ' ';
  std::cout << '\n';
  for (auto b: bs) std::cout << std::fixed << b << ' '; 
  std::cout << '\n';
  for (auto c: cs) std::cout << std::fixed << c << ' '; 
  std::cout << '\n';
  for (auto d: ds) std::cout << std::fixed << d << ' '; 
  std::cout << '\n';
}


Output is
1 2 3 4 
0 1 1 2 
0.500000 1.000000 1.500000 2.000000 
2.000000 4.000000 6.000000 8.000000 


C++ 20 also provides transform_view which is conceptually very similar.
https://en.cppreference.com/w/cpp/ranges/transform_view
Last edited on
@JLBorges, This solution is close to what I was looking for. Can it use a predefined function instead of a lambda? That would solve my problem.
> Can it use a predefined function instead of a lambda?

Yes. It is a template; FN could be any suitable callable type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <vector>
#include <concepts>

struct caller_t
{
    // overload the call operator for vectors of integral types
    // (apply the function FN to each element of the vector)
    template < std::integral T, typename FN >
    std::vector<T> operator() ( const std::vector<T>& vec, const FN& fn ) const
    { auto result = vec ; for( auto& v : result ) v = fn(v) ; return result ; }
};

// pre-defined functions
int plus_1( int v ) noexcept { return v+1 ; }
template < std::integral T > T minus_20( T v ) noexcept { return v-T(20) ; }

int main()
{
    const std::vector<int> vec { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } ;
    const caller_t caller ; // function object

    const auto vec_p1 = caller( vec, plus_1 ) ; // call operator: add 1 to each element
    for( int v : vec_p1 ) std::cout << v << ' ' ; // 1 2 3 4 5 6 7 8 9 10
    std::cout << '\n' ;

    const auto vec_p100 = caller( vec, minus_20<int> ) ;  // call operator: subtract 20 from each int element
    for( int v : vec_p100 ) std::cout << v << ' ' ; // -20 -19 -18 -17 -16 -15 -14 -13 -12 -11
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/35ef83e3a18cca67
@JLBorges, Thank you very much. This is good enough.
Topic archived. No new replies allowed.