5

在尝试回答这个问题时,我想建议使用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<boost::is_polymorphic<T>, void>*)[with T = N]
test.cpp:20:注意: void* address_of(T*, boost::disable_if<boost::is_polymorphic<T>, void>*)[with T = N ]

在我看来,这里应该使用哪种重载似乎相当清楚。我的意思是很明显我已经定义了一个替代方法,一次只能使用一个函数......我原以为 SFINAE 会处理使不必要的重载无效。

...我通过使用(ellipsis) 而不是并需要一个虚拟的第二个参数来修补它disable_if......但我仍然对编译器为什么会窒息感兴趣。

4

2 回答 2

11

编译器窒息,因为你忘记了::type尾随enable_ifand disable_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); }

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

于 2010-08-16T10:07:58.023 回答
0

在 3.4.4 中使用 enable_if 的“返回类型”版本: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;
}
于 2010-08-16T09:23:31.710 回答