作为函数模板的 T* 参数传递时使用运算符 T* 强制模板类

发布于 2024-07-06 09:39:41 字数 666 浏览 9 评论 0原文

假设我有一个像这样的函数模板:

template<class T>
inline
void
doStuff(T* arr)
{
  // stuff that needs to use sizeof(T)
}

然后在另一个 .h 文件中,我有一个模板类 Foo ,其中包含:

public: operator T*() const;

现在,我意识到这些是不同的 T。 但是如果我有一个变量 Foo; f 在堆栈上,将其强制为任何类型指针的唯一方法是调用运算符 T*()。 然而,如果调用 doStuff(f),GCC 会抱怨 doStuff 无法采用 Foo 而不是自动使用运算符 T*() 强制转换为 Bar*,然后将 Bar 的函数模板专门化为 T

我可以做些什么来使这两个模板一起工作吗? 或者模板函数的参数必须是真正的指针类型,还是将带有强制运算符的模板类传递给非模板函数?

Assume I have a function template like this:

template<class T>
inline
void
doStuff(T* arr)
{
  // stuff that needs to use sizeof(T)
}

Then in another .h filee I have a template class Foo that has:

public: operator T*() const;

Now, I realize that those are different Ts. But If I have a variable Foo<Bar> f on the stack, the only way to coerce it to any kind of pointer would be to invoke operator T*(). Yet, if call doStuff(f), GCC complains that doStuff can't take Foo<Bar> instead of automatically using operator T*() to coerce to Bar* and then specializing the function template with Bar as T.

Is there anything I can do to make this work with two templates? Or does either the argument of the template function have to be a real pointer type or the template class with the coercion operator be passed to a non-template function?

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

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

发布评论

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

评论(5

小女人ら 2024-07-13 09:39:41

海湾合作委员会是正确的。 在模板参数中,仅考虑完全匹配,而不考虑类型转换。 这是因为否则可能必须考虑无限(或至少指数)数量的转换。

如果 Foo是您要运行的唯一其他模板,最好的解决方案是添加:

template<typename T> inline void doStuff(const Foo<T>& arr) {
    doStuff(static_cast<T*>(arr));
}

如果您在很多模板中遇到此问题,这个应该可以解决它:

#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/enable_if.hpp>
template<template <typename> class T, typename U> inline typename boost::enable_if<typename boost::is_convertible<T<U>, U*>::type>::type doStuff(const T<U>& arr) {
    doStuff(static_cast<U*>(arr));
}

不过它有点冗长;-)

GCC is correct. In template arguments only exact matches are considered, type conversions are not. This is because otherwise an infinite (or at least exponential) amount of conversions could have to be considered.

If Foo<T> is the only other template that you're going to run in to, the best solution would be to add:

template<typename T> inline void doStuff(const Foo<T>& arr) {
    doStuff(static_cast<T*>(arr));
}

If you are having this issue with a lot of templates, this one should fix it:

#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/enable_if.hpp>
template<template <typename> class T, typename U> inline typename boost::enable_if<typename boost::is_convertible<T<U>, U*>::type>::type doStuff(const T<U>& arr) {
    doStuff(static_cast<U*>(arr));
}

It's a bit verbose though ;-)

面犯桃花 2024-07-13 09:39:41

这可能值得一试:

doStuff<Bar>(f);

我认为这将导致编译器期望 T* 为 Bar*,然后使用 Foo 的运算符 T*() 来执行转换,但我不能说我已经尝试过。

This might be worth a try:

doStuff<Bar>(f);

I think this will cause the compiler to expect T* to be Bar* and then use Foo's operator T*() to perform the cast, but I can't say I've tried it.

风透绣罗衣 2024-07-13 09:39:41

莱昂的想法可能是最好的。 但在紧要关头,您也可以显式调用强制转换运算符:

doStuff(static_cast<Bar*>(f));

Leon's idea is probably best. But in a pinch, you could also call the cast operator explicitly:

doStuff(static_cast<Bar*>(f));
毁我热情 2024-07-13 09:39:41

我不确定为什么转换不起作用,但您可以使用重载来解决问题


template 
inline
void 
doStuff(T& arrRef)
{
  doStuff(&arrRef);
}

I'm not sure why the conversion doesn't work but you could use an overload to fix the problem


template 
inline
void 
doStuff(T& arrRef)
{
  doStuff(&arrRef);
}
水水月牙 2024-07-13 09:39:41

嗯,T* 并不是您所认为的与 T 不同的类型。 指针是一个类型限定符。 我不确定标准对此有何规定,但我想说,由于变量已经是 T 类型,因此它不会再次尝试转换。 如果您想做一些自定义的事情来获取指针,请重载 & 操作员。

Well, T* is not a separate type from T in the sense you think it is. The pointer is a type qualifier. I'm not sure what the standard says about it, but I would say that as the variable is already of type T it does not try to convert again. If you want to do some custom stuff to get a pointer, overload the & operator.

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