c++关于模板化类型和类层次结构的函数重载决策

发布于 2024-08-24 21:50:20 字数 767 浏览 3 评论 0原文

可能的重复:
在 C++ 中选择重载模板函数时的优先级

模板化函数给出我可以方便地操作各种类型:

template<typename T> void destroy(T* obj) {
    delete obj;
}

但在某些时候,我想对类层次结构进行一些专门化:

class Base { virtual void doSomething(); };
class Derived : public Base {};
void destroy(Base* obj) {
    obj->doSomething();
    delete obj;
}

但是,如果我传递确切的类型Base*,则确实会调用预期的专门函数如果我将 Derived* 传递给 void detroy(),重载解析的规则似乎更喜欢通用模板化版本,而不是执行静态向上转换。

当然,我可以为所有可能的派生类型创建所有重载函数,但它的可维护性较差。

我使用的是 Visual C++ 2008,有什么办法可以解决上述问题吗?

Possible Duplicate:
Priority when choosing overloaded template functions in C++

A templated function gives me the convenience to operate on a variety of types:

template<typename T> void destroy(T* obj) {
    delete obj;
}

But at some point I want to do some specialization on a class hierarchy:

class Base { virtual void doSomething(); };
class Derived : public Base {};
void destroy(Base* obj) {
    obj->doSomething();
    delete obj;
}

The intended specialized function did invoked if I a pass the exact type Base*, however the rules of overload resolution seems to prefer the generic templated version instead of performing a static up cast if I a pass Derived* to void detroy().

Certainly I can make all the overloaded functions for all possible derived types, but it's less maintainable.

I am using Visual C++ 2008, is there any way around the above problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

感性不性感 2024-08-31 21:51:18

不存在 Visual C++ 2009 这样的东西。

您可以使用另一个模板来专门化您的函数,并使用 SFINAE 来仅匹配 Base 的子类型。但我不知道编译器有什么理由更喜欢第二个版本,通常必须在某些方面选择“更好”的专业化。

或者,您可以使用 SFINAE 和辅助特征类来防止通用版本匹配 Base 的子类。如果您需要这方面的示例,请询问。

当然,您的专业知识只会在可见的地方使用。模板化函数始终是内联的,它们和专业化需要位于调用者包含的头文件中。

There's no such thing as Visual C++ 2009.

You may be able to specialize your function with another template and use SFINAE to only match subtypes of Base. But I don't know any reason the compiler would prefer the second version, usually a specialization has to be "better" in some way to be selected.

Alternatively, you could use SFINAE and a helper traits class to prevent the generic version from matching subclasses of Base. If you need an example of this, ask.

And of course your specialization will only be used where it's visible. Templated functions are always inline, they and specializations need to be in header files included by the caller.

野稚 2024-08-31 21:51:12

在所有条件相同的情况下,重载解析更喜欢非模板函数而不是函数模板。然而,在这种情况下,并不是所有事情都是平等的。为了匹配 Base* 的重载,需要进行派生到基指针的转换;无需转换即可匹配函数模板。因此,函数模板被选择为Derived*

“简单”(尽管可能容易出错)的解决方案是在调用函数之前将 Derived* 转换为 Base*

至少在理论上,您可以按照 Ben 的建议采用 SFINAE 方法,但是您必须显式禁用您提供专业化的任何类型的通用函数模板,否则您最终会遇到重载歧义。这比显式强制转换方法更难以维护且更容易出错。 (不过,这里的某人可能知道另一种方法来解决过载歧义;我当然有兴趣知道是否有)。

All things being equal, overload resolution prefers nontemplate functions to function templates. However, in this case, all things are not equal. To match your overload for Base*, a derived-to-base pointer conversion is necessary; no conversion is necessary to match the function template. Thus, the function template is selected for Derived*.

The "simple," albeit probably error-prone, solution would be to cast your Derived* to a Base* before you call the function.

You could, in theory at least, take an SFINAE approach as Ben suggests, but you would have to explicitly disable the generic function template for any types for which you provide specializations, otherwise you'll end up with overload ambiguities. This is even more unmaintainable and error-prone than the explicit cast approach. (Though, someone here may know of another way to get around the overload ambiguity; I'd certainly be interested to know if there was).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文