【问题标题】:Unused constructor instantiated in template class created by another constructor在另一个构造函数创建的模板类中实例化的未使用构造函数
【发布时间】:2022-01-31 02:45:01
【问题描述】:

我有以下课程:

template <typename T=void>
class Foo{
public:

  Foo(){};

  template <typename = typename std::enable_if_t<!std::is_void<T>::value, std::nullptr_t>>
  Foo(const T&){};

};

int main() {
  Foo<void> v;
}

v 是使用第一个构造函数创建的。因此,无需为Foo&lt;void&gt; 创建第二个构造函数。

为什么还是要创建它?

问题是显式创建类型为void 的第二个构造函数会绕过SFINAE,并尝试创建const void&amp; 的参数。这显然是不允许的。

如果Tvoid,如何防止第二个构造函数有效?

【问题讨论】:

    标签: c++ templates void sfinae enable-if


    【解决方案1】:

    为什么还是要创建它?

    因为在你的模板构造函数中

    template <typename = typename std::enable_if_t<!std::is_void<T>::value, std::nullptr_t>>
    Foo(const T&){};
    

    std::enable_if (!std::is_void&lt;T&gt;::value) 的测试值取决于类的模板类型 (T)。

    要使 SFINAE 启用/禁用类(或结构)的方法,您必须编写一个依赖于方法本身的模板参数的测试。

    解决此问题的一种方法是为该方法添加一个模板参数U,并将其指定为T 作为默认类型。我的意思是

    template <typename U = T,
              typename = std::enable_if_t<!std::is_void<U>::value, std::nullptr_t>>
    Foo(const U&){} // ..... the test depends from U ---^
    //        ^--- U also here, to avoid the void reference problem
    

    或者,也许更好,

    template <typename U = T, 
              std::enable_if_t<!std::is_void<U>::value, std::nullptr_t> = nullptr>
    Foo(const U&){}
    

    【讨论】:

    • U 处于推断上下文中,允许Foo&lt;void&gt; v = 1。你可以把它放在一个非推断的上下文中,并将它与enable_if 结合起来,比如:template&lt;typename U = T&gt; Foo(const std::enable_if_t&lt;!std::is_void_v&lt;U&gt;, U&gt;&amp;){}
    【解决方案2】:

    T 为无效时,禁用构造函数的另一种方法是用一些不可用的类型替换const T&amp;

    struct unusable {
      unusable() = delete;
      unusable(const unusable&) = delete;
      ~unusable() = delete;
    };
    
    template <typename T=void>
    class Foo{
      using cref = std::conditional_t<std::is_void_v<T>, unusable, std::add_lvalue_reference_t<const T>>;
    public:
    
      Foo(){}
    
      Foo(cref){}
    
    };
    

    这很有用 const T&amp; 它在多个地方使用,因此您不必在任何地方都使用 SFINAE。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-09
      • 2019-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多