是否可以根据某事物是否为常量表达式来覆盖函数和/或模板?
基本上我想做的是构建一个字符串类,如果传递一个静态字符串或一个指向一个的 constexpr 变量,它将简单地使用该指针,以后不会尝试删除它。
另一方面,如果给类一个缓冲区,它需要复制或采用它,然后在析构函数中删除它。
我认为最接近的可能是使用强类型定义并要求程序员在该类型定义下声明他/她的静态字符串。我想知道那些比我聪明的人是否能想出一些不需要的东西。
是否可以根据某事物是否为常量表达式来覆盖函数和/或模板?
基本上我想做的是构建一个字符串类,如果传递一个静态字符串或一个指向一个的 constexpr 变量,它将简单地使用该指针,以后不会尝试删除它。
另一方面,如果给类一个缓冲区,它需要复制或采用它,然后在析构函数中删除它。
我认为最接近的可能是使用强类型定义并要求程序员在该类型定义下声明他/她的静态字符串。我想知道那些比我聪明的人是否能想出一些不需要的东西。
基本上我想做的是构建一个字符串类,如果传递一个静态字符串或一个指向一个的 constexpr 变量,它将简单地使用该指针,以后不会尝试删除它。
我认为我们在这里面临一个XY 问题。知道一个表达式是不是constexpr
,并不能告诉你它是否适合delete
.
我会说如果这个操作可能不合适,该函数不应该尝试猜测是否删除。我相信调用者应该注意这一点,可能使用智能指针来处理它。
换句话说,如果必须将指向的对象作为参数传递给函数,我会让函数接受左值引用,并让客户端取消引用指针。
我想说这种模式不仅在以下情况下有意义delete
:更一般地说,如果一段代码负责决定如何生成或计算某些值(例如对象分配),那么还有责任正确执行一些相关或相应的操作(例如清理)应该属于同一段代码:
void foo(my_object& o)
{
// ...
}
my_object o;
foo(o);
// The argument has automatic storage, no need to delete
my_object* pO = new my_object();
foo(*pO);
// The argument was allocated through operator new, we must
// deallocate it through a corresponding call to delete
delete pO;
如果您真的希望在函数中进行清理,您应该为客户端提供一种方法来告诉函数如何执行它:
void foo(my_object& o, bool shouldDelete)
{
// ...
if (shouldDelete) { delete &o; }
}
my_object o;
foo(o, false); // "And don't try to deallocate this object please..."
my_object* pO = new my_object();
foo(*pO, true); // "Please, delete it for me" (we are delegating the
// responsibility of performing the material action,
// but not the one of knowing how!)
为了获得更大的灵活性,您甚至可以接受一个可调用对象,这通过“委派执行实质性操作的责任,而不是知道如何执行的责任”,使我在上述评论中的意思更加清楚:
#include <functional>
void foo(my_object& o, std::function<void()> f = [] () { })
{
// ...
f();
}
int main()
{
my_object o;
foo(o); // "And don't do anything with this object when you're done..."
my_object* pO = new my_object();
foo(*pO, [=] () { delete pO; }); // "Please, do exactly this when done..."
}
如果您不需要在运行时确定可调用对象的类型,您甚至可以考虑转为foo()
函数模板。
最后,关于您最初关于如何确定表达式是否为常量表达式的问题,这通常是不可能的,但有一些技术可以在某些情况下帮助您 - 请注意它们的局限性。在这方面,您可能会发现StackOverflow 上的此问答相关。