如何应用使默认构造函数有条件地显式

How can I apply make a default constructor conditionally explicit?

本文关键字:有条件 构造函数 默认 何应用 应用      更新时间:2023-10-16

>问题

假设我们有一个(虚构的(类模板C<T>,其中包含一个有条件显式的默认构造函数。默认构造函数应该是显式的,当且仅当 std::is_same_v<T, int> .

搜索"[c++] 有条件显式"将返回以下结果:构造函数有条件地标记为显式。

失败的解决方案

接受的答案给出了一个例子:

struct S {
  template <typename T,
             typename std::enable_if<std::is_integral<T>::value, bool>::type = false >
  S(T) {}
  template <typename T,
            typename std::enable_if<!std::is_integral<T>::value, bool>::type = false>
  explicit S(T) {}
};

稍微修改示例会给出这个实现,它使用熟悉的std::enable_if方法:

template <class T>
class C {
public:
  template <std::enable_if_t<std::is_same_v<T, int>, int> = 0>
  C() {}
  template <std::enable_if_t<!std::is_same_v<T, int>, int> = 0>
  explicit C() {}
};

不幸的是,这甚至没有编译:演示

prog.cc: In instantiation of 'class C<int>':
prog.cc:15:10:   required from here
prog.cc:10:12: error: no type named 'type' in 'struct std::enable_if<false, int>'
   10 |   explicit C() {}
      |            ^
prog.cc: In instantiation of 'class C<double>':
prog.cc:18:13:   required from here
prog.cc:7:3: error: no type named 'type' in 'struct std::enable_if<false, int>'
    7 |   C() {}
      |   ^

该问题似乎是由于省略了构造函数的模板参数,禁用了 SFINAE。

问题

  1. 为什么这不编译?
  2. 什么是可能的实现?

如果可能的话,我想避免专门上课。

  1. 什么是可能的实现?

你试过吗

template <class T>
class C {
public: //  VVVVVVVVVVVVVV .................................V  U here, not T
  template <typename U = T, std::enable_if_t<std::is_same_v<U, int>, int> = 0>
  C() {}
  template <typename U = T, std::enable_if_t<!std::is_same_v<U, int>, int> = 0>
  explicit C() {}
};

  1. 为什么这不编译?

问题在于,在类方法之上,SFINAE 使用方法本身的模板参数。

这是在原始工作代码中:

  template <typename T,
             typename std::enable_if<std::is_integral<T>::value, bool>::type = false >
  S(T) {}

其中T是特定于构造函数的模板参数(从单个参数推导(。

相反,在你失败的代码中,

template <std::enable_if_t<std::is_same_v<T, int>, int> = 0>
C() {}

构造函数正在计算类(T(的模板参数,而不是方法的模板参数。

使用技巧typename U = T,您可以转换类的模板参数T,在U中,方法的模板参数(在您的情况下是构造函数,但也适用于其他方法(,因此std::enable_if_t,根据U进行测试,能够启用/禁用构造函数。