Home > database >  How to overload call operator() function with same type and parameters, but different return type?
How to overload call operator() function with same type and parameters, but different return type?

Time:12-05

I want to define a new call operator() function with the parameters and type defined for the first operator() function. The reason for doing this is that the operations I want to perform with the new operator() function needs the same parameters as the first one, but maybe named differently but the type I need should remain the same. I know that it is not possible, but could someone suggest any different method to do this or are there any way around?

code listing:

namespace correlator {
    class mean_square_displacement
    {
    public: 
        typedef std::shared_ptr<boost::multi_array<float, 2>> sample_type;
        typedef double result_type;  // fixed_vector<double, 3>

    result_type operator() (sample_type const& first, sample_type const& second) const
    { 
        double msd = 0;
        size_t N = first->size(); // number of rows in one frame (11214 in one frame)
        
        for (unsigned int i = 0; i < N;   i) {
            for (unsigned int j = 0; j < 3;   j) {
                double dr = (*first)[i][j] - (*second)[i][j];
                msd  = dr * dr;
                //ofile_msd << i << " " << msd << std::endl;
                if (msd > 0)
                    std::cout << "msd::" <<  msd << std::endl;
        } 
    }
    
    return msd/N;
} // first operator ends here 

    double operator()(sample_type const& first, sample_type const& second) const
    {
        std::cout <<  *(*first)[0][0] <<"The first element :." << std::endl;
        
        return 0;
    }
};
} // namespace correlator

CodePudding user response:

Adapters:

struct Foo {
  // these are your current operator() functions
  int op1(int);
  float op2(int);
};

struct FooAdapter1 {
  Foo& foo;
  auto operator()(int i) { return foo.op1(i); }
};

struct FooAdapter2 {
  Foo& foo;
  auto operator()(int i) { return foo.op2(i); }
};

So, instead of passing a Foo object like this:

std::invoke(foo,7); // no

You pass it via an adapter:

std::invoke(FooAdapter1{foo},7); // calls op1

And you give the Adapters good semantically sensible names, of course.


Alternatively, use an out argument to select the overload:

struct Foo {
  // these are your current operator() functions
  void operator()(int, int&);
  void operator()(int, float&);
};

And then the somewhat ugly call:

float& result{};
std::invoke(foo,7,result); // selects the fist overload
  •  Tags:  
  • c
  • Related