如何使用 SFINAE 启用转换运算符的显式隐式?
How to use SFINAE to enable implicitness of explicitness of the conversion operator?
考虑以下代码:
// Preamble
#include <iostream>
#include <type_traits>
// Wrapper
template <class From>
struct wrapper
{
// Implicit conversion
template <class To, class = typename std::enable_if<
std::is_convertible<From, To>::value
>::type>
constexpr operator To() const noexcept;
// Explicit conversion
template <class To, class = typename std::enable_if<
!std::is_convertible<From, To>::value
&& std::is_constructible<To, From>::value
>::type>
explicit constexpr operator To() const noexcept;
};
// Main
int main(int argc, char* argv[])
{
wrapper<int> x;
double y = x;
return 0;
}
理想情况下,当 From
可隐式转换为 To
时,此代码将使转换运算符隐式化,并在 To
可从 [=12= 显式构造时使转换运算符显式化].
但是,代码目前无法编译,因为从编译器的角度来看,两个转换运算符具有相同的签名。
问题:是否有任何方法可以欺骗编译器产生预期的行为?
答案: 完整代码基于 的答案:
// Preamble
#include <iostream>
#include <type_traits>
// Wrapper
template <class From>
struct wrapper
{
// Implicit conversion
template <class To, typename std::enable_if<
std::is_convertible<From, To>::value,
int>::type = 0>
constexpr operator To() const noexcept(noexcept(From{})) {
return From{};
}
// Explicit conversion
template <class To, typename std::enable_if<
!std::is_convertible<From, To>::value
&& std::is_constructible<To, From>::value,
int>::type = 0>
explicit constexpr operator To() const noexcept(noexcept(From{})) {
return From{};
}
};
// Main
int main(int argc, char* argv[])
{
wrapper<int> x;
double y = x;
return 0;
}
是的,只需将您的 class = typename std::enable_if<...>::type
模式替换为 typename std::enable_if<..., int>::type = 0
。然后 SFINAE 参数是一个不同类型的非类型模板参数,函数重载 corrctly。
考虑以下代码:
// Preamble
#include <iostream>
#include <type_traits>
// Wrapper
template <class From>
struct wrapper
{
// Implicit conversion
template <class To, class = typename std::enable_if<
std::is_convertible<From, To>::value
>::type>
constexpr operator To() const noexcept;
// Explicit conversion
template <class To, class = typename std::enable_if<
!std::is_convertible<From, To>::value
&& std::is_constructible<To, From>::value
>::type>
explicit constexpr operator To() const noexcept;
};
// Main
int main(int argc, char* argv[])
{
wrapper<int> x;
double y = x;
return 0;
}
理想情况下,当 From
可隐式转换为 To
时,此代码将使转换运算符隐式化,并在 To
可从 [=12= 显式构造时使转换运算符显式化].
但是,代码目前无法编译,因为从编译器的角度来看,两个转换运算符具有相同的签名。
问题:是否有任何方法可以欺骗编译器产生预期的行为?
答案: 完整代码基于
// Preamble
#include <iostream>
#include <type_traits>
// Wrapper
template <class From>
struct wrapper
{
// Implicit conversion
template <class To, typename std::enable_if<
std::is_convertible<From, To>::value,
int>::type = 0>
constexpr operator To() const noexcept(noexcept(From{})) {
return From{};
}
// Explicit conversion
template <class To, typename std::enable_if<
!std::is_convertible<From, To>::value
&& std::is_constructible<To, From>::value,
int>::type = 0>
explicit constexpr operator To() const noexcept(noexcept(From{})) {
return From{};
}
};
// Main
int main(int argc, char* argv[])
{
wrapper<int> x;
double y = x;
return 0;
}
是的,只需将您的 class = typename std::enable_if<...>::type
模式替换为 typename std::enable_if<..., int>::type = 0
。然后 SFINAE 参数是一个不同类型的非类型模板参数,函数重载 corrctly。