0

Explicit constructor calls are supported by clang (this->ClassName::ClassName()) with -fms-extensions thanks!

template<int k>
class Base {
public:
    int num = 0;
    Base(int sdsd):num(sdsd) {}
    void func(int v) {num = 12 + v;}
};


template <int Ty>
void callA(Base<Ty> *obj){
    (reinterpret_cast< Base<Ty>*>(obj))->Base::Base(1); // error: cannot refer to type member 'Base' in 'Base<99>' with '->'
                                                        // but with MS compiler in windows that's right

    (reinterpret_cast< Base<Ty>*>(obj))->Base::func(1); // ok
}
void callB(void *obj){
    (reinterpret_cast< Base<100>*>(obj))->Base::Base(2);// ok
    (reinterpret_cast< Base<100>*>(obj))->Base::func(1); // ok
}

int main(int argn, char** argc) {
    Base<99> a(0);
    callA(&a);
    callB(&a);
}
吴带爷
  • 27
  • 3
  • 4
    What is this? Calling `reinterpret_cast` to convert to a completely different template instance sounds like undefined behavior to me. What is the purpose of trying to directly invoke a constructor? Are you trying to emulate _placement-new_? – paddy Dec 04 '20 at 06:16
  • [When to use reinterpret_cast](https://stackoverflow.com/questions/573294/when-to-use-reinterpret-cast) reinterpret_cast(v) is a forced conversion, such as (type)v, but this conversion often reports errors – 吴带爷 Dec 04 '20 at 07:25
  • in fact, (reinterpret_cast< Base*>(obj)). <=> ((Base) (void*) obj) – 吴带爷 Dec 04 '20 at 07:28
  • Two completely unrelated class template instances are not convertible. The behavior here I think is either undefined or implementation specific. I know what `reinterpret_cast` does, and it is NOT there just to get around a fundamental error caused by you attempting something fundamentally dangerous. – paddy Dec 04 '20 at 07:31
  • Isn't . ```obj->Base::Base(1); ``` Still error, ```reinterpret_cast ``` is not the point – 吴带爷 Dec 04 '20 at 07:35
  • Yes. My point is that using `reinterpret_cast` is not a solution, as you're trying to trick the compiler into thinking it's not an error. – paddy Dec 04 '20 at 07:41
  • You sure this has something to do with templates? If I remember correctly, it's simply not allowed by the standard (so MSVC is misbehaving). – HolyBlackCat Dec 04 '20 at 08:01

1 Answers1

-1

ok, I find the solution;just use new (obj) Base<Ty>(1);Call explicit constructor/destructor with traits in templatized function

吴带爷
  • 27
  • 3
  • This is called _placement-new_, which I mentioned in my original comment. However, you cannot do this in your `callB` function, if that's what you think you're doing. This is _undefined behavior_. What this does is overwrite the original object, re-using its memory to construct the new object in its place. The problem here is that the compiler still thinks that `a` is of type `Base<99>` and will use that class's destructor later. For your trivial example it "works" by chance, but for a real example this is super-duper dangerous. All my comments about `reinterpret_cast` apply. – paddy Dec 04 '20 at 09:26
  • To expand on this, it's also an error in `callA`, because you have not used _placement-delete_. Again, trivial examples "work", but essentially here you have simply overwritten a valid object's memory with that of a newly-constructed object in its stead. At best, nothing bad happens. More commonly, you leak memory. At worst, all hell breaks loose! – paddy Dec 04 '20 at 09:33
  • sorry! I did not understand what you mean by "placement-new", everything is normal now [my code](https://github.com/notify-bibi/TriggerBug/blob/master/src/engine/basic_var.hpp). Thank you, you are correct. – 吴带爷 Dec 04 '20 at 15:16