In designing a DSL (which compiles into C++), I found it convenient to define a wrapper class that, uppon destruction, would call a .free() method on the contained class:
template<class T> 
class freeOnDestroy : public T {
    using T::T;
public:
    operator T&() const { return *this; }
    ~freeOnDestroy() { T::free(); }
};
The wrapper is designed to be completely transparent: All methods, overloads and constructors are inherited from T (at least to my knowledge), but when included in the wrapper, the free() method is called uppon destruction. Note that I explicitly avoid using T's destructor for this since T::free() and ~T() may have different semantics!
All this works fine, untill a wrapped class gets used as a member to a non-reference templated call, at which point freeOnDestroy is instantiated, calling free on the wrapped object. What I would like to happen is for the tempated method to use T instead of freeOnDestroy<T>, and to implicitly cast the parameter into the supperclass. The following code sample illustrates this problem:
// First class that has a free (and will be used in foo)
class C{
    int * arr;
public:
    C(int size){ 
        arr = new int[size]; 
        for (int i = 0; i < size; i++) arr[i] = i;
    }
    int operator[] (int idx) { return arr[idx]; }
    void free(){ cout << "free called!\n"; delete []arr; }
};
// Second class that has a free (and is also used in foo)
class V{
    int cval;
public:
    V(int cval) : cval(cval) {}
    int operator[] (int idx) { return cval; }
    void free(){}   
};
// Foo: in this case, accepts anything with operator[int]
// Foo cannot be assumed to be written as T &in!
// Foo in actuality may have many differently-templated parameters, not just one
template<typename T>
void foo(T in){
    for(int i = 0; i < 5; i++) cout << in[i] << ' ';
    cout << '\n';
}
int main(void){
    C c(15);
    V v(1);
    freeOnDestroy<C> f_c(15);
    foo(c); // OK!
    foo(v); // OK!
    foo<C>(f_c); // OK, but the base (C) of f_c may not be explicitly known at the call site, for example, if f_c is itself received as a template
    foo(f_c); // BAD: Creates a new freeOnDestroy<C> by implicit copy constructor, and uppon completion calls C::free, deleting arr! Would prefer it call foo<C>
    foo(f_c); // OH NO! Tries to print arr, but it has been deleted by previous call! Segmentation fault :(
    return 0;
}
A few non solutions I should mention are:
- Making freeOnDestroy::freeOnDestroy(const freeOnDestroy &src)explicit and private, but this seems to overrideT's constructor. I'd hoped it would try to implicitly convert it toTand use that as the template argument.
- Assume fooreceives a reference of its templated arguments (as invoid foo(T &in): This is neither the case, nor desirable in some cases
- Always explicitly template the call to foo, as infoo<C>(f_c):f_citself may be templated, so it's hard to know to instantiatefoowithC(yes, this could be done with creating multiple versions offoo, to remove the wrappers one by one, but I can't find a way of doing that without creating a different overload for each templated argument offoo).
In summary, my question is: Is there a clean(ish) method to ensure a base class will be casted to its superclass when resolving a template? Or, if not, is there some way of using SFINAE, by causing a substitution failure when the template argument is an instance of the wrapper class, and thus force it to use the implicit cast to the wrapped class (without duplicating each foo-like method signature possibly dozens of times)?
I presently have a work-arround that involves changes in the DSL, but I'm not entirely happy with it, and was curious if it was at all possible to design a wrapper class that works as described.
 
     
     
    