启用_如果+ disable_if 组合会引发不明确的调用

发布于 2024-09-14 04:20:06 字数 1431 浏览 1 评论 0 原文

在尝试回答这个问题时,我想建议使用enable_if + disable_if 允许基于类型是(或不是)多态的事实来重载方法。

所以我创建了一个小测试文件:

template <class T>
void* address_of(T* p,
                 boost::enable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return dynamic_cast<void*>(p); }

template <class T>
void* address_of(T* p,
                 boost::disable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return static_cast<void*>(p); }

struct N { int x; };


int main(int argc, char* argv[])
{
  N n;
  std::cout << address_of(&n) << std::endl;
  return 0;
}

这看起来很温和。

然而 gcc (3.4 ...) 对此感到窒息:

test.cpp:在函数int main(int, char**)中:
test.cpp:29: 错误:重载 address_of(N*) 的调用不明确
test.cpp:17:注意:候选者是:void* address_of(T*, boost::enable_if, void>*) [其中 T = N]
test.cpp:20: 注意:void* address_of(T*, boost::disable_if, void>*) [其中 T = N]

对于我来说,这里应该使用哪种重载似乎相当清楚。我的意思是,很明显,我已经定义了一种替代方法,一次只能使用一个函数……而且我本以为 SFINAE 会负责使不必要的重载失效。

我通过使用 ... (省略号)而不是 disable_if 来修补它,并需要一个虚拟的第二个参数...但我仍然对为什么编译器对此感到困惑很感兴趣。

While trying to answer this question I wanted to suggest the use of enable_if + disable_if to allow the overload of a method based on the fact that a type was (or not) polymorphic.

So I created a small test file:

template <class T>
void* address_of(T* p,
                 boost::enable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return dynamic_cast<void*>(p); }

template <class T>
void* address_of(T* p,
                 boost::disable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return static_cast<void*>(p); }

struct N { int x; };


int main(int argc, char* argv[])
{
  N n;
  std::cout << address_of(&n) << std::endl;
  return 0;
}

which seems quite tame.

However gcc (3.4 ...) choke on this:

test.cpp: In function int main(int, char**):
test.cpp:29: error: call of overloaded address_of(N*) is ambiguous
test.cpp:17: note: candidates are: void* address_of(T*,
boost::enable_if<boost::is_polymorphic<T>, void>*)
[with T = N]
test.cpp:20: note: void* address_of(T*,
boost::disable_if<boost::is_polymorphic<T>, void>*)
[with T = N]

It seems rather clear to my human mind which overload should be used here. I mean it seems clear that I have defined an alternative and only one function can be used at a time... and I would have thought that SFINAE would take care of invalidating the unnecessary overload.

I patched it up by using ... (ellipsis) instead of disable_if and requiring a dummy second argument... but I am still interested in why the compiler choke on this.

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

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

发布评论

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

评论(2

救星 2024-09-21 04:20:06

编译器卡住了,因为您忘记了 enable_ifdisable_if 上的尾随 ::type。模板总是被定义的;只是当且仅当表达式为 true(对于 enable_if)或 false 时,成员 type 才存在>(对于 disable_if)。

template <class T>
void* address_of(T* p,
                 typename boost::enable_if< boost::is_polymorphic<T> >::type* dummy = 0)
{ return dynamic_cast<void*>(p); }

template <class T>
void* address_of(T* p,
                 typename boost::disable_if< boost::is_polymorphic<T> >::type* dummy = 0)
{ return static_cast<void*>(p); }

如果没有尾随 ::type,您的函数模板只会创建重载,将指向 enable_ifdisable_if 实例的指针作为第二个参数。使用尾随的 ::type,模板要么使用类型为 void* 的第二个参数创建重载,要么删除重载(即所需的行为)。

The compiler choked because you forgot the trailing ::type on enable_if and disable_if. The templates are always defined; it is just that the member type is present if and only if the expression is true (for enable_if) or false (for disable_if).

template <class T>
void* address_of(T* p,
                 typename boost::enable_if< boost::is_polymorphic<T> >::type* dummy = 0)
{ return dynamic_cast<void*>(p); }

template <class T>
void* address_of(T* p,
                 typename boost::disable_if< boost::is_polymorphic<T> >::type* dummy = 0)
{ return static_cast<void*>(p); }

Without the trailing ::type, your function templates just create overloads that take pointers to instances of enable_if or disable_if as the second parameter. With the trailing ::type, the templates either create an overload with a second parameter of type void*, or the overload is removed (i.e. the desired behaviour).

绾颜 2024-09-21 04:20:06

使用enable_if的“返回类型”版本适用于3.4.4:gcc版本3.4.4(cygming特殊,gdc 0.12,使用dmd 0.125)

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <iostream>

template <class T>
typename boost::enable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return dynamic_cast<void*>(p); }

template <class T>
typename boost::disable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return static_cast<void*>(p); }

struct N { int x; };


int main(int argc, char* argv[])
{
  N n;
  std::cout << address_of(&n) << std::endl;
  return 0;
}

Using the "return type" version of enable_if works in 3.4.4: gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <iostream>

template <class T>
typename boost::enable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return dynamic_cast<void*>(p); }

template <class T>
typename boost::disable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return static_cast<void*>(p); }

struct N { int x; };


int main(int argc, char* argv[])
{
  N n;
  std::cout << address_of(&n) << std::endl;
  return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文