enable_if + disable_if组合会引发一个模糊的调用

Mat*_* M. 5 c++ gcc boost enable-if

在尝试回答这个问题时,我想建议使用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;
}
Run Code Online (Sandbox Code Playgroud)

这看起来很温顺.

然而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<boost::is_polymorphic<T>, void>*)[有T = N]
test.cpp:20:注意: void* address_of(T*, boost::disable_if<boost::is_polymorphic<T>, void>*)[有T = N ]

我的人类思维似乎很清楚这里应该使用过载.我的意思是很明显,我已经定义了一个替代方案,并且一次只能使用一个函数......而且我认为SFINAE会照顾无效的过载.

我通过使用...(省略号)代替disable_if并且需要一个虚拟的第二个参数来修补它...但我仍然对编译器为何扼杀这个问题感兴趣.

Ant*_*ams 11

编译器哽咽,因为你忘了尾随::typeenable_ifdisable_if.始终定义模板; type当且仅当表达式为true(for enable_if)或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); }
Run Code Online (Sandbox Code Playgroud)

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