模板类型推导涉及嵌套模板参数和默认值

时间:2014-09-16 04:30:02

标签: c++ templates c++11

我有以下代码:

#include <type_traits>
#include <memory>

class CDelegateCore {};

class CDelegate : public CDelegateCore {};

class CEvent
{
   private:

      /// Simple empty enumeration used for enable_if test.
      enum class enabler_t {};

      template<typename T>
      using EnableIf = typename std::enable_if<T::value, enabler_t>::type;

   public:

      CEvent() {}
      ~CEvent() {}

      void operator += (CDelegateCore* func) {}

      template<typename T, typename Deleter, EnableIf<std::is_base_of<CDelegateCore, T>> = enabler_t{}>
      void operator += (std::unique_ptr<T, Deleter> const& func) { *this += func.get(); }
};

int main()
{
    std::unique_ptr<CDelegate> testdel;
    // ... initialize testdel ...

    CEvent EVENT;
    EVENT += testdel;
}

此处的目标是,当CDelegate拥有std::unique_ptr时,+=使用CEvent的{​​{1}}重载将被调用,将推导std::enable_if内的模板参数。

此代码在GCC和Clang中正常工作,但在MSVC12中失败。它无法解决该功能。谁能告诉我为什么?我最初没有为unique_ptr删除器设置模板参数,并且它有效,但是我不确定C ++中有关使用默认嵌套模板参数的类型推导的规则。

2 个答案:

答案 0 :(得分:3)

我不确定这一点,但我相信这是因为VS2013缺乏表达SFINAE支持。如果将enable_if表达式移动到operator+=

的返回类型,则可以使代码在VS2013(以及gcc和clang)上运行
template<typename T, typename Deleter>
typename std::enable_if<std::is_base_of<CDelegateCore, T>::value>::type
  operator += (std::unique_ptr<T, Deleter> const& func) { *this += func.get(); }

您可以使用EnableIf别名,将第二个模板参数更改为void,或者只使用std::enable_if_t(gcc和clang上需要-std=c++1y)。

Live demo

答案 1 :(得分:0)

VS2013支持SFINAE或至少大部分。 改变

template<typename T, typename Deleter, EnableIf<std::is_base_of<CDelegateCore, T>> = enabler_t{}>

template<typename T, typename Deleter, class = EnableIf<std::is_base_of<CDelegateCore, T>>>