0

I am writing array functions** (e.g. transpose) and often want to have both in situ and ex situ versions of the same function. The in situ version is faster but changes the original array. The ex situ version is used if you need to keep the original unchanged, but it's slower since it has to make a copy. I would like the two versions of the function to have the same name, but I know you can't distinguish functions in C++ by return type alone. I thought of a way of doing it by changing the array parameter into a const for the ex situ version, but I'm concerned there may be issues with this approach since I couldn't find it mentioned anywhere (e.g. Overload a C++ function according to the return value)

// in situ version
void square(int* ip, int size)
{
  for (int i = 0; i < size; i++)
    ip[i] *= ip[i];
}

// ex situ version
int* square(int const* icp, int size)
{   
  int* ip = new int[size];

  for (int i = 0; i < size; i++)
    ip[i] = icp[i] * icp[i];

  return ip;
}

// usage
int main()
{
  int a[5] = {0, 1, 2, 3, 4};

  square(a, 5);
  // now a = {0, 1, 4, 9, 16}

  int* b = square(const_cast<int const*>(a), 5);
  // a still = {0, 1, 4, 9, 16}
  // b = {0, 1, 16, 81, 256}
  ...
  delete[] b;
  ...
  return 0;
}

Any feedback much appreciated thanks.

** I'm aware there are standard containers and libraries for doing some of this (std::vector, boost::array). However I'm working on a C++ DLL to be called from Excel/VBA, so the arrays arrive in my C++ program as raw pointers. Since performance is a priority, converting them into standard containers and back is unappealing.

Community
  • 1
  • 1
George Skelton
  • 1,095
  • 1
  • 10
  • 22
  • You are asking for trouble. In your case the best option is to avoid overloading altogether. – Daniel Daranas Jul 11 '14 at 14:29
  • Related: [Inconsistent use of const qualifier between declaration and definition](http://stackoverflow.com/a/20659598/1708801). It will work but it is very odd. You would be better off using two different names. – Shafik Yaghmour Jul 11 '14 at 14:31
  • You can use the standard algorithms on raw pointers. see: http://stackoverflow.com/questions/16445957/can-raw-pointers-be-used-instead-of-iterators-with-stl-algorithms-for-containers – user1937198 Jul 11 '14 at 14:35
  • Thanks everyone, good points and links – George Skelton Jul 11 '14 at 15:09

2 Answers2

3

Please don't do that, it's going to confuse your users quite a lot. Make two different functions with two different names.

zmbq
  • 38,013
  • 14
  • 101
  • 171
1

Write a functor to square it and let the user decide using transform. (In this simple case a function can be used instead of a functor)

template<class T>
T square(const T& x)
{
    return x*x;
}

int *in, *out;
size_t size;

std::transform(in, in + size, out, square<int>); // ex situ
std::transform(in, in + size, in, square<int>); // in situ
Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
  • Thanks this seems to be a satisfactory approach `template f(T* in, int size, T* out) { if (in == out) /* in situ version */ else /* ex situ version */ }` Obviously makes more sense for functions like transpose (rather than square) which actually have a difference between the in & ex situ versions! – George Skelton Jul 12 '14 at 11:02