使用 std::enable_if 重载 std::unique_ptr 删除器方法
Overload std::unique_ptr deleter method using std::enable_if
我正在尝试为我的 std::unique_ptr
编写一个删除器,我想重载删除方法。这是我尝试过的,但是编译器抱怨使用 std::enable_if_t
。代码是使用 -std=c++20
标志编译的。
template <class T>
class custom_deleter
{
public:
template <class U, std::enable_if_t<std::is_array_v<T>, bool> = true>
void operator()(U* ptr) { std::cout << "array"; }
template <class U, std::enable_if_t<!std::is_array_v<T>, bool> = true>
void operator()(U* ptr) { std::cout << "non-array"; }
};
这是编译器错误:
main.cpp:17:10: error: no type named 'type' in 'struct std::enable_if<false, bool>'
17 | void operator()(U* ptr) { std::cout << "non-array"; }
| ^~~~~~~~
我不明白这个问题。起初,我以为我缺少 std::enable_if_t
可用的包含或编译标志,但这不是这里的问题。任何帮助表示赞赏。
SFINAE 需要依赖函数的模板参数。这意味着 std::enable_if_t
只能应用于 U
而不能应用于 class 模板 T
。因此,您需要以某种方式(如 class U = T
)或 if constexpr
the operator()
as you are anyway have acces to c++20:
在 operator()
中包含模板参数 T
template <class T>
class custom_deleter
{
public:
template <class U = T>
void operator()(U* ptr)
{
if constexpr(std::is_array_v<U>) std::cout << "array";
else if constexpr(!std::is_array_v<U>) std::cout << "non-array";
}
};
int main()
{
custom_deleter<int[2]> arrDel;
custom_deleter<std::string> strDel;
return 0;
}
SFINAE 在选择要调用的函数时启动,但您的条件仅取决于 T
而不是 U
。实际上不确定这是否是正确的解释,sfinae 让我头晕:P。当您使用 C++20 时,我建议使用 constexpr if
而不是 SFINAE。无论如何,这编译:
#include <iostream>
#include <type_traits>
template <class T>
class custom_deleter
{
public:
template <class U,class W=T, std::enable_if_t<!std::is_array_v<W>, bool> = true>
void operator()(U* ptr) { std::cout << "non-array"; }
template <class U,class W=T, std::enable_if_t<std::is_array_v<W>, bool> = true>
void operator()(U* ptr) { std::cout << "array"; }
};
int main(){
custom_deleter<int> p{};
p("asd");
}
再想一想.. 为什么会有 U
和 T
?您不想 custom_deleter<T>
删除 T
吗?我想你真的想要这个:
template <class T>
class custom_deleter
{
public:
template <class U=T, std::enable_if_t<!std::is_array_v<U>, bool> = true>
void operator()(U* ptr) { std::cout << "non-array"; }
template <class U=T, std::enable_if_t<std::is_array_v<U>, bool> = true>
void operator()(U* ptr) { std::cout << "array"; }
};
int main(){
custom_deleter<int> p{};
}
我正在尝试为我的 std::unique_ptr
编写一个删除器,我想重载删除方法。这是我尝试过的,但是编译器抱怨使用 std::enable_if_t
。代码是使用 -std=c++20
标志编译的。
template <class T>
class custom_deleter
{
public:
template <class U, std::enable_if_t<std::is_array_v<T>, bool> = true>
void operator()(U* ptr) { std::cout << "array"; }
template <class U, std::enable_if_t<!std::is_array_v<T>, bool> = true>
void operator()(U* ptr) { std::cout << "non-array"; }
};
这是编译器错误:
main.cpp:17:10: error: no type named 'type' in 'struct std::enable_if<false, bool>'
17 | void operator()(U* ptr) { std::cout << "non-array"; }
| ^~~~~~~~
我不明白这个问题。起初,我以为我缺少 std::enable_if_t
可用的包含或编译标志,但这不是这里的问题。任何帮助表示赞赏。
SFINAE 需要依赖函数的模板参数。这意味着 std::enable_if_t
只能应用于 U
而不能应用于 class 模板 T
。因此,您需要以某种方式(如 class U = T
)或 if constexpr
the operator()
as you are anyway have acces to c++20:
operator()
中包含模板参数 T
template <class T>
class custom_deleter
{
public:
template <class U = T>
void operator()(U* ptr)
{
if constexpr(std::is_array_v<U>) std::cout << "array";
else if constexpr(!std::is_array_v<U>) std::cout << "non-array";
}
};
int main()
{
custom_deleter<int[2]> arrDel;
custom_deleter<std::string> strDel;
return 0;
}
SFINAE 在选择要调用的函数时启动,但您的条件仅取决于 T
而不是 U
。实际上不确定这是否是正确的解释,sfinae 让我头晕:P。当您使用 C++20 时,我建议使用 constexpr if
而不是 SFINAE。无论如何,这编译:
#include <iostream>
#include <type_traits>
template <class T>
class custom_deleter
{
public:
template <class U,class W=T, std::enable_if_t<!std::is_array_v<W>, bool> = true>
void operator()(U* ptr) { std::cout << "non-array"; }
template <class U,class W=T, std::enable_if_t<std::is_array_v<W>, bool> = true>
void operator()(U* ptr) { std::cout << "array"; }
};
int main(){
custom_deleter<int> p{};
p("asd");
}
再想一想.. 为什么会有 U
和 T
?您不想 custom_deleter<T>
删除 T
吗?我想你真的想要这个:
template <class T>
class custom_deleter
{
public:
template <class U=T, std::enable_if_t<!std::is_array_v<U>, bool> = true>
void operator()(U* ptr) { std::cout << "non-array"; }
template <class U=T, std::enable_if_t<std::is_array_v<U>, bool> = true>
void operator()(U* ptr) { std::cout << "array"; }
};
int main(){
custom_deleter<int> p{};
}