[英]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&
的參數。 這顯然是不允許的。
如果T
為void
,如何防止第二個構造函數有效?
為什么它仍然被創建?
因為在您的模板構造函數中
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.