2

I have a class with an implicit conversion operator to a pointer. Deallocating that pointer is not valid. Can I prevent the conversion to a pointer when used with the delete[] operator? I would like a compile time error. For the free function, I can delete an overload that takes the class as an argument.

void foobar(double*){}

struct A {
  // Please pretend I have a good reason for doing this.
  operator double*() const { return nullptr; }
};

void free(A&) = delete;

int main(){
  A a;
  
  // Just works TM
  foobar(a);

  // This compiles :(
  delete[] a;
  // This does not :)
  //free(a);
  return 0;
}

I think something clever would be needed for the desired effect.


A use case for implicit conversion: Say A implements a scoped array. Conversion makes A almost a drop in replacement for an alloc/dealloc pair. Templates and iterators requiring explicit conversion. Otherwise the call sites of c-like functions remain unchanged.

6
  • 1
    Although std::free(a) would compile even with your code Commented Oct 27, 2020 at 20:19
  • 8
    Do you need the conversion operator to be implicit? Marking it explicit would solve the problem. Commented Oct 27, 2020 at 20:19
  • 3
    You could add a operator void*() const { return nullptr; } to make it an ambiguous situation. Commented Oct 27, 2020 at 20:39
  • @Eljay That seems to be an answer! With limited use so far, I'm not seeing other inconvenient ambiguities either. Might still have some though. Side effect of -Wdelete-incomplete existing instead of just being an error. Commented Oct 27, 2020 at 21:04
  • Do you really need a conversion operator, and not a simpler method? double* A::toDoublePtr() const { return ...; } Commented Oct 27, 2020 at 22:20

2 Answers 2

2

As a workaround, you can prevent the conversion to a pointer when used with the delete[] operator by making the conversion ambiguous.

However, depending on the situation of the rest of the code, this may cause undesirable ambiguity for the desired use cases.

struct A {
  operator double*() const { return nullptr; }
  operator void*() const { return nullptr; }
};
Sign up to request clarification or add additional context in comments.

Comments

0

Whenever it comes to stopping something at compile time you can think of using templates.

void foobar(double*){}

class A {
  // Please pretend I have a good reason for doing this.
  public : 
  operator double*() const { return nullptr; }
  template<typename type>
  void operator delete[] (void*, type size); 
};

template<typename type>
void free(void*);

template<>
void free<A>(void*) = delete;

int main(){
  A a;
  
  // Just works TM
  foobar(a);

  // Now this will not compile to ! :(
  delete[] a;
  // This does not :)
  //free(a);
  return 0;
}

3 Comments

This didn't work. Without delete[] a; I still get "error: expected unqualified-id before ‘delete’" @ void delete[] (...Tried compiling with g++ -std=c++17 foo.cpp
Actually , I have mistaken, therefore I have modified my answer and this finally works
The updated version compiles even with delete[] a;. The defined delete is not a candidate to be called. I'm not sure there is a way to make defining that operator work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.