【问题标题】:Explicit constructor calls with template are not supported by clangclang 不支持使用模板的显式构造函数调用
【发布时间】:2020-12-04 15:53:33
【问题描述】:

带有 -fms-extensions 的 clang (this->ClassName::ClassName()) 支持显式构造函数调用 谢谢!

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);
}

【问题讨论】:

  • 这是什么?调用reinterpret_cast 转换为完全不同的模板实例对我来说听起来像是未定义的行为。尝试直接调用构造函数的目的是什么?您是否在尝试模拟 placement-new
  • When to use reinterpret_castreinterpret_cast(v)是强制转换,比如(type)v,但是这种转换经常报错
  • 事实上,(reinterpret_cast*>(obj))。 ((Base) (void*) obj)
  • 两个完全不相关的类模板实例是不可转换的。我认为这里的行为是未定义的或特定于实现的。我知道reinterpret_cast 做了什么,它不只是为了解决由于您尝试一些根本性危险的事情而导致的根本性错误。
  • 不是。 obj-&gt;Base::Base(1); 还是错误,reinterpret_cast 不是重点

标签: c++


【解决方案1】:

好的,我找到了解决方案;只需使用new (obj) Base&lt;Ty&gt;(1);Call explicit constructor/destructor with traits in templatized function

【讨论】:

  • 这叫做 placement-new,我在原始评论中提到过。但是,如果您认为自己正在这样做,则不能在 callB 函数中执行此操作。这是未定义的行为。这样做是覆盖原始对象,重新使用其内存在其位置构造新对象。这里的问题是编译器仍然认为aBase&lt;99&gt; 类型并且稍后会使用该类的析构函数。对于您的微不足道的示例,它偶然“起作用”,但对于一个真实的示例,这是超级危险的。我所有关于reinterpret_cast的cmets都适用。
  • 在此展开,callA也报错,因为你没有使用placement-delete。再一次,简单的例子“工作”,但基本上在这里你只是简单地用一个新构造的对象的内存覆盖了一个有效对象的内存。充其量,没有什么不好的事情发生。更常见的是,您会泄漏内存。在最坏的情况下,一切都会崩溃!
  • 对不起!我不明白您所说的“新安置”是什么意思,现在一切正常my code。谢谢,你是对的。
猜你喜欢
  • 2016-06-07
  • 1970-01-01
  • 2019-03-14
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多