Как использовать SFINAE, чтобы включить неявность явности оператора преобразования?
Рассмотрим следующий код:
// 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
явно конструируем из From
,
Однако в настоящее время код не компилируется, поскольку с точки зрения компилятора оба оператора преобразования имеют одинаковую сигнатуру.
Вопрос: есть ли способ обмануть компилятор для получения ожидаемого поведения?
Ответ: полный код, основанный на ответе Квентина:
// 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;
}
1 ответ
Решение
Да просто замени class = typename std::enable_if<...>::type
шаблон с typename std::enable_if<..., int>::type = 0
, В этом случае параметр SFINAE является нетиповым параметром шаблона другого типа, и функции перегружаются.