【问题标题】:enable_if + disable_if combination provokes an ambiguous callenable_if + disable_if 组合引发模棱两可的调用
【发布时间】:2011-03-30 08:13:53
【问题描述】:

在尝试回答 this question 时,我想建议使用 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 会处理使不必要的重载无效的问题。

我使用...(省略号)而不是disable_if 对其进行了修补,并且需要一个虚拟的第二个参数......但我仍然对编译器为什么会阻塞这个问题感兴趣。

【问题讨论】:

    标签: c++ gcc boost enable-if


    【解决方案1】:

    编译器阻塞是因为您忘记了 enable_ifdisable_if 上的尾随 ::type。模板总是被定义的;只是成员 type 存在当且仅当表达式为 true(对于 enable_if)或 false(对于 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* 类型的第二个参数创建重载,要么删除重载(即所需的行为)。

    【讨论】:

      【解决方案2】:

      在 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;
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-21
        • 2010-11-18
        • 1970-01-01
        • 1970-01-01
        • 2014-09-28
        • 2011-07-23
        • 1970-01-01
        • 1970-01-01
        • 2019-09-13
        相关资源
        最近更新 更多