Неявное преобразование между типами шаблонов - PullRequest
0 голосов
/ 09 февраля 2019

Я создал два типа: bool_t и number_t, и я хотел преобразовать один в другой (двумя способами).Однако у меня возникли проблемы с преобразованием bool_t в number_t.

. В основном я хочу сделать следующее (но он не компилируется):

template<bool v>
struct bool_t {
    template<template<int> typename T>
    operator T<v ? 1 : 0>() {
        return {};
    }
};

template<int N>
struct number_t {
template<int n1, int n2>
friend number_t<n1 + n2> operator+(number_t<n1>, number_t<n2>) {
  return {};
}
};


int main() {
    number_t<0>{} + bool_t<0>{};   
}

иошибка:

prog.cc:19:19: error: invalid operands to binary expression ('number_t<0>' and 'bool_t<0>')
    number_t<0>{} + bool_t<0>{};   
    ~~~~~~~~~~~~~ ^ ~~~~~~~~~~~
prog.cc:12:26: note: candidate template ignored: could not match 'number_t' against 'bool_t'
friend number_t<n1 + n2> operator+(number_t<n1>, number_t<n2>) {
                         ^
1 error generated.

Как решить эту проблему?

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Определяемые пользователем преобразования никогда не рассматриваются при попытке сопоставления типов аргументов функции с типами параметров функции для вывода аргументов шаблона.Так что эта проблема представляет собой несколько более сложную версию ошибки такого рода:

template <int> struct X {};
struct Y {
    operator X<2> () const { return {}; }
};
template <int N>
void f(X<N>) {}

int main()
{
    Y y;
    f(y); // Error: Cannot deduce template argument.
}

Так как кажется, что вы делаете что-то вроде библиотеки шаблонного метапрограммирования, возможно, вы могли бы определить собственный механизмдля преобразования типов в вашей библиотеке "в шаблон"?

#include <type_traits>

template<bool v>
struct bool_t {
    // (Add some appropriate SFINAE.)
    template<template<int> typename T>
    constexpr T<v ? 1 : 0> convert_template() const {
        return {};
    }
};

template<typename T, template<int> class TT>
struct type_specializes : std::false_type {};

template<template<int> class TT, int N>
struct type_specializes<TT<N>, TT> : std::true_type {};

template<int N>
struct number_t {
    // Allow "conversion" to my own template:
    template<template<int> typename T>
    constexpr std::enable_if_t<type_specializes<number_t, T>::value, number_t>
    convert_template() const { return {}; }

private:
    // Used only in decltype; no definition needed.
    template<int n1, int n2>
    static number_t<n1 + n2> sum_impl(number_t<n1>, number_t<n2>);

    template<typename T1, typename T2>
    friend auto operator+(T1&& x, T2&& y)
        -> decltype(number_t::sum_impl(
             x.template convert_template<number_t>(),
             y.template convert_template<number_t>()))
    { return {}; }
};

int main() {
    number_t<0>{} + bool_t<0>{};   
}

Если вы хотите, чтобы оба операнда были bool_t специализациями, operator+ должен быть правильным видимым членом пространства имен;Вы можете добавить больше проверок SFINAE, если это необходимо.

0 голосов
/ 09 февраля 2019

Ваша проблема сводится к тому, что язык допускает самое большее одно неявное преобразование.

Тогда одним из решений будет сделать функцию, принимающую также bool_t:

number_t<n1 + n2> operator+(number_t<n1>, bool_t<n2>) {
  //return something
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...