Определяемые пользователем преобразования никогда не рассматриваются при попытке сопоставления типов аргументов функции с типами параметров функции для вывода аргументов шаблона.Так что эта проблема представляет собой несколько более сложную версию ошибки такого рода:
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, если это необходимо.