Как использовать SFINAE, чтобы включить неявность явности оператора преобразования? - PullRequest
0 голосов
/ 29 октября 2018

Рассмотрим следующий код:

// 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 Ответ

0 голосов
/ 29 октября 2018

Да, просто замените ваш шаблон class = typename std::enable_if<...>::type на typename std::enable_if<..., int>::type = 0. Тогда параметр SFINAE является нетиповым параметром шаблона другого типа, и функции перегружаются по всем параметрам.

...