【问题标题】:Template type deduction involving nested template parameters and defaults涉及嵌套模板参数和默认值的模板类型推导
【发布时间】:2023-03-24 21:25:01
【问题描述】:

我有以下代码:

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

这里的目标是,当我拥有由std::unique_ptr 拥有的CDelegate 时,将调用CEvent 中利用std::enable_if+= 重载,并推导出std::unique_ptr 中的模板参数.

此代码在 GCC 和 Clang 中运行良好,但在 MSVC12 中失败。无法解析该功能。谁能告诉我为什么?我最初没有用于 unique_ptr 删除器的模板参数,但它确实有效,但我不确定 C++ 中关于使用默认嵌套模板参数进行类型推导的规则是什么。

【问题讨论】:

    标签: c++ templates c++11


    【解决方案1】:

    我不确定这一点,但我相信这是因为 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(); }
    

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

    Live demo

    【讨论】:

    • 由于缺乏适当的 SFINAE 支持,我无法从 Microsoft 找到文档。您在哪里找到您的信息?
    • @void.pointer This 表显示 VS2013 和 VS14 都不支持表达式 SFINAE。但正如我所提到的,我不确定这是不是这样的效果。我预计用于 SFINAE 的 decltype 表达式在 VS2013 上不起作用,但在您的示例中不起作用。可能是他们的 SFINAE 支持的其余部分也不完整,或者至少是错误的。
    【解决方案2】:

    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>>>
    

    【讨论】:

    • 什么是 class= 语法?
    • 具有默认类型的未命名模板参数。
    猜你喜欢
    • 2015-08-15
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 2023-01-24
    • 2022-11-01
    • 2016-12-30
    • 1970-01-01
    • 2018-07-16
    相关资源
    最近更新 更多