调用模板 class 的析构函数,预期 class-name 在 ‘(’ 标记之前
Call the destructor of a template class, expected class-name before ‘(’ token
我有一个例外情况,我需要调用 class 的析构函数来清除联合内存。我们还不能使用 std::variant
。联合中的 class 是基于模板的,其定义类似于:
template<class TYPE>
class BaseTemplate
{
public:
BaseTemplate() = default;
~BaseTemplate() = default;
// Other useful functions.
private:
TYPE value;
}
现在我们定义不同的类型使用:
using X = BaseTemplate<int>;
// Other using definitions
在较早的情况下 X
是从 BaseTemplate
.
派生的 classes
class X : public BaseTemplate<int>
{
X() = default;
~X() override = default; // In this case ~BaseTemplate was virtual.
// Nothing useful so we would like to remove this class.
};
在以前的情况下,我们可以这样调用析构函数:
X variableX;
variableX.~X();
在使用 using X = BaseTemplate<int>;
的新情况下,这会导致错误:expected class-name before ‘(’ token
。那么在这种情况下我该如何调用析构函数呢?
复制代码:
#include <iostream>
namespace a
{
class Base
{
public:
Base() = default;
virtual ~Base() = default;
virtual void foo() = 0;
};
template<class TYPE>
class BaseTemplate : public Base
{
public:
BaseTemplate() = default;
~BaseTemplate() override = default;
// Other useful functions.
void set(const TYPE& v)
{
value = v;
}
TYPE get() const
{
return value;
}
void foo() final
{
value *= 2;
}
private:
TYPE value;
};
using X = BaseTemplate<int>;
using Y = BaseTemplate<unsigned int>;
using Z = BaseTemplate<float>;
} // End of namespace a
union XYZ
{
XYZ() {}
~XYZ() {}
a::X variableX;
a::Y variableY;
a::Z variableZ;
};
XYZ xyz;
int main()
{
// Inplace new operator to initialize x
new(&xyz.variableX) a::X;
xyz.variableX.set(1);
xyz.variableX.foo();
std::cout << "Result: " << xyz.variableX.get() << std::endl;
xyz.variableX.~X();
}
variableX
的析构函数称为 ~BaseTemplate()
。但是,如果 X
在范围内并解析为 BaseTemplate<int>
,它也将用作析构函数的别名。
如果 X
不在范围内:
some::random_namespace::X variableX;
// variableX.~X(); X not in scope, will not work
variableX.some::random_namespace::X::~X(); // Works, but confusing
// variableX.~decltype(variableX)(); // Supposed to work, but GCC does not like
using T = decltype(variableX); variableX.~T();
using X = some::random_namespace::X; variableX.~X();
using some::random_namespace::X; variableX.~X(); // Now in scope
真正的解决办法是使用std::destroy_at(std::addressof(variableX))
std::destroy_at(&variableX); // Does not care about the name of the destructor
我有一个例外情况,我需要调用 class 的析构函数来清除联合内存。我们还不能使用 std::variant
。联合中的 class 是基于模板的,其定义类似于:
template<class TYPE>
class BaseTemplate
{
public:
BaseTemplate() = default;
~BaseTemplate() = default;
// Other useful functions.
private:
TYPE value;
}
现在我们定义不同的类型使用:
using X = BaseTemplate<int>;
// Other using definitions
在较早的情况下 X
是从 BaseTemplate
.
class X : public BaseTemplate<int>
{
X() = default;
~X() override = default; // In this case ~BaseTemplate was virtual.
// Nothing useful so we would like to remove this class.
};
在以前的情况下,我们可以这样调用析构函数:
X variableX;
variableX.~X();
在使用 using X = BaseTemplate<int>;
的新情况下,这会导致错误:expected class-name before ‘(’ token
。那么在这种情况下我该如何调用析构函数呢?
复制代码:
#include <iostream>
namespace a
{
class Base
{
public:
Base() = default;
virtual ~Base() = default;
virtual void foo() = 0;
};
template<class TYPE>
class BaseTemplate : public Base
{
public:
BaseTemplate() = default;
~BaseTemplate() override = default;
// Other useful functions.
void set(const TYPE& v)
{
value = v;
}
TYPE get() const
{
return value;
}
void foo() final
{
value *= 2;
}
private:
TYPE value;
};
using X = BaseTemplate<int>;
using Y = BaseTemplate<unsigned int>;
using Z = BaseTemplate<float>;
} // End of namespace a
union XYZ
{
XYZ() {}
~XYZ() {}
a::X variableX;
a::Y variableY;
a::Z variableZ;
};
XYZ xyz;
int main()
{
// Inplace new operator to initialize x
new(&xyz.variableX) a::X;
xyz.variableX.set(1);
xyz.variableX.foo();
std::cout << "Result: " << xyz.variableX.get() << std::endl;
xyz.variableX.~X();
}
variableX
的析构函数称为 ~BaseTemplate()
。但是,如果 X
在范围内并解析为 BaseTemplate<int>
,它也将用作析构函数的别名。
如果 X
不在范围内:
some::random_namespace::X variableX;
// variableX.~X(); X not in scope, will not work
variableX.some::random_namespace::X::~X(); // Works, but confusing
// variableX.~decltype(variableX)(); // Supposed to work, but GCC does not like
using T = decltype(variableX); variableX.~T();
using X = some::random_namespace::X; variableX.~X();
using some::random_namespace::X; variableX.~X(); // Now in scope
真正的解决办法是使用std::destroy_at(std::addressof(variableX))
std::destroy_at(&variableX); // Does not care about the name of the destructor