6

I'm trying to wrapping an object and want to pass it as a pointer to functions. The object is known can be cast to limited types and I want to provide cast operator for these types. For example:

class MyInt {
  public:
    MyInt() {}
    MyInt(int val): int32_storage_(val), int64_storage_(val*2) {}

    const int32_t* GetInt32Ptr() const { return &int32_storage_; }
    const int64_t* GetInt64Ptr() const { return &int64_storage_; }

  private:
    int32_t int32_storage_ = 0;
    int64_t int64_storage_ = 0;
};


int32_t int32_add(const int32_t* iptr_a, const int32_t* const iptr_b) {
  return *iptr_a + *iptr_b;
}

int64_t int64_add(const int64_t* iptr_a, const int64_t* const iptr_b) {
  return *iptr_a + *iptr_b;
}


int main() {
  MyInt a(10);
  MyInt b(20);

  std::cout << "32bit a + b = " << int32_add(a.GetInt32Ptr(), b.GetInt32Ptr()) << std::endl;
  std::cout << "64bit a + b = " << int64_add(a.GetInt64Ptr(), b.GetInt64Ptr()) << std::endl;

  return 0;
}

What I expected is to replace GetInt32Ptr() with a cast operator so I can call int32_add() like this int32_add(&a, &b). I tried

    const int32_t*() const { return &int32_storage_; }
    const int64_t*() const { return &int64_storage_; }

but it doesn't work.

jasonxia
  • 321
  • 1
  • 8

3 Answers3

8

You're almost there, the correct syntax for the operator definition is:

operator const int32_t*() const { return &int32_storage_; }
operator const int64_t*() const { return &int64_storage_; }

Also note that as described here, you can also make these operators explicit, which is often desired to guard against unwanted conversions. It requires more verbosity, when doing the conversion, e.g. static_cast<const int32_t*>(a) instead of just a.

lubgr
  • 37,368
  • 3
  • 66
  • 117
  • I have tried this, and got error like this:` test.cpp:37:36: error: no matching function for call to 'int32_add' std::cout << "32bit a + b = " << int32_add(&a, &b) << std::endl; ^~~~~~~~~ test.cpp:20:9: note: candidate function not viable: no known conversion from 'MyInt *' to 'const int32_t *' (aka 'const int *') for 1st argument int32_t int32_add(const int32_t * iptr_a, const int32_t* const iptr_b) { ` – jasonxia Jul 03 '19 at 08:32
  • Call it as `int32_add(a, b)`, the conversion operator will do the rest. No need to manually request the address. – lubgr Jul 03 '19 at 08:33
  • Thanks @lubgr, it works! Because the parameter is a pointer so I hope it could be `int32_add(&a, &b)`. It more easy for reader knows the parameter is a pointer. Is that possible? – jasonxia Jul 03 '19 at 08:40
  • Well then you need to return a reference to the data member, e.g. `operator const int32_t&() const`. – lubgr Jul 03 '19 at 08:46
3

When you want the type to implicitly convert into another you have to declare that as an operator method:

operator const int32_t*() const { return &int32_storage_; }
operator const int64_t*() const { return &int64_storage_; }

Now, in order to call the functions just say a, b and they are implicitly converted:

std::cout << "32bit a + b = " << int32_add(a, b) << std::endl;
std::cout << "32bit a + b = " << int64_add(a, b) << std::endl;

Note: your function qualifiers aren't consistent (const int32_t*)

they all should be const T* const

also std::endl is generally wrong, replace it with '\n' - reasoning

Stack Danny
  • 7,754
  • 2
  • 26
  • 55
1

you are missing the operator keyword.

operator const int32_t* () const { return &int32_storage_; }
operator const int64_t* () const { return &int64_storage_; }
robthebloke
  • 9,331
  • 9
  • 12