簡體   English   中英

在由另一個構造函數創建的模板 class 中實例化的未使用構造函數

[英]Unused constructor instantiated in template class created by another constructor

我有以下 class:

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<void>創建第二個構造函數。

為什么它仍然被創建?

問題是顯式創建具有void類型的第二個構造函數會繞過 SFINAE,並嘗試創建const void&的參數。 這顯然是不允許的。

如果Tvoid ,如何防止第二個構造函數有效?

為什么它仍然被創建?

因為在您的模板構造函數中

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

std::enable_if ( :std::is_void<T>::value ) 的測試值取決於 class ( T ) 的模板類型。

要 SFINAE 啟用/禁用 class(或結構)的方法,您必須編寫依賴於方法本身的模板參數的測試。

規避此問題的一種方法是為該方法添加一個模板參數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&){}

禁用構造函數的另一種方法是在T為 void 時將const T&替換為一些不可用的類型:

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&它在多個地方使用,因此您不必在任何地方都使用 SFINAE。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM