我需要编写第二个 SFINAE 构造函数吗?
What I need write this second SFINAE constructor?
我想在参数包中的所有类型都不同时激活带有参数包的 class。我写了一个像这样的小辅助函数,没有问题:
template<typename T, typename... Ts>
constexpr bool has_duplicate_types() {
if constexpr (sizeof...(Ts) == 0)
return false;
else
return ((std::is_same_v<std::decay_t<T>, std::decay_t<Ts>> || ...) || has_duplicate_types<Ts...>());
}
当我尝试使用 SFINAE 激活我的 class 时,我尝试了几种方法,有效的方法是:
template<typename T, typename dummy = void, typename... Ts>
struct XYZ_imp {
XYZ_imp() {
std::cout << "ok\n";
}
};
template<typename T, typename... Ts>
struct XYZ_imp<T, std::enable_if_t<has_duplicate_types<T, Ts...>()>, Ts...> {
XYZ_imp() = delete;
};
template<typename T, typename... Ts>
using XYZ = XYZ_imp<T, void, Ts...>;
但是如您所见,代码太多了。但是当我试着这样写的时候:
template<typename T, typename... Ts>
struct XYZ {
template<typename U = T, std::enable_if_t<has_duplicate_types<U, Ts...>(), int> = 0>
XYZ() = delete;
};
我不知道为什么它不起作用。当存在类似 XYZ<int,int>
的类型时它按预期工作并且它说构造函数被删除,但是当类型不同时 XYZ<int,double>
,我得到以下错误:
no matching function for call to 'XYZ<int, double>::XYZ()'
如果我像这样编写另一个 SFINAE 构造函数:
template<typename T, typename... Ts>
struct XYZ {
template<typename U = T, std::enable_if_t<has_duplicate_types<U, Ts...>(), int> = 0>
XYZ() = delete;
template<typename U = T, std::enable_if_t<!has_duplicate_types<U, Ts...>(), int> = 0>
XYZ() {
std::cout << "ok\n";
}
};
它会工作,但我不知道为什么我需要写第二个并且它不会自动选择默认的一个。知道为什么吗?
If I write another SFINAE constructor like this: ... It will work, but I have no idea why I need to write 2nd one and it does not pick defaulted one without it automatically.
如果您定义任何自定义构造函数,即使该构造函数被 SFINAE 禁用,编译器也不会生成默认构造函数。
并且由于您需要编写非 =delete
d 构造函数,您不妨删除 =delete
d 构造函数:
template<typename T, typename... Ts>
struct XYZ
{
template <typename U = T, std::enable_if_t<!has_duplicate_types<U, Ts...>(), int> = 0>
XYZ()
{
std::cout << "ok\n";
}
};
我想在参数包中的所有类型都不同时激活带有参数包的 class。我写了一个像这样的小辅助函数,没有问题:
template<typename T, typename... Ts>
constexpr bool has_duplicate_types() {
if constexpr (sizeof...(Ts) == 0)
return false;
else
return ((std::is_same_v<std::decay_t<T>, std::decay_t<Ts>> || ...) || has_duplicate_types<Ts...>());
}
当我尝试使用 SFINAE 激活我的 class 时,我尝试了几种方法,有效的方法是:
template<typename T, typename dummy = void, typename... Ts>
struct XYZ_imp {
XYZ_imp() {
std::cout << "ok\n";
}
};
template<typename T, typename... Ts>
struct XYZ_imp<T, std::enable_if_t<has_duplicate_types<T, Ts...>()>, Ts...> {
XYZ_imp() = delete;
};
template<typename T, typename... Ts>
using XYZ = XYZ_imp<T, void, Ts...>;
但是如您所见,代码太多了。但是当我试着这样写的时候:
template<typename T, typename... Ts>
struct XYZ {
template<typename U = T, std::enable_if_t<has_duplicate_types<U, Ts...>(), int> = 0>
XYZ() = delete;
};
我不知道为什么它不起作用。当存在类似 XYZ<int,int>
的类型时它按预期工作并且它说构造函数被删除,但是当类型不同时 XYZ<int,double>
,我得到以下错误:
no matching function for call to 'XYZ<int, double>::XYZ()'
如果我像这样编写另一个 SFINAE 构造函数:
template<typename T, typename... Ts>
struct XYZ {
template<typename U = T, std::enable_if_t<has_duplicate_types<U, Ts...>(), int> = 0>
XYZ() = delete;
template<typename U = T, std::enable_if_t<!has_duplicate_types<U, Ts...>(), int> = 0>
XYZ() {
std::cout << "ok\n";
}
};
它会工作,但我不知道为什么我需要写第二个并且它不会自动选择默认的一个。知道为什么吗?
If I write another SFINAE constructor like this: ... It will work, but I have no idea why I need to write 2nd one and it does not pick defaulted one without it automatically.
如果您定义任何自定义构造函数,即使该构造函数被 SFINAE 禁用,编译器也不会生成默认构造函数。
并且由于您需要编写非 =delete
d 构造函数,您不妨删除 =delete
d 构造函数:
template<typename T, typename... Ts>
struct XYZ
{
template <typename U = T, std::enable_if_t<!has_duplicate_types<U, Ts...>(), int> = 0>
XYZ()
{
std::cout << "ok\n";
}
};