Я хотел бы создать шаблонный класс test<T>
, который я могу преобразовать в test<U>
(возможно, неявно), если T
конвертируется в U
. Самая простая идея, которая пришла мне в голову, - добавить шаблонный конструктор, который принимает test<U>
, где аргумент шаблона U
находится под управлением enable_if
.Преобразовать класс <T> к классу <U>, если T конвертируется в U
#include <iostream>
#include <type_traits>
template <typename T>
class test {
int _foo;
public:
int foo() const { return _foo; }
test() : _foo(5) {}
// This works:
// template <typename U>
// test(test<U> other)
// : _foo(other.foo()) {}
// This doesn't, can't resolve `U`:
template <typename U>
test(test<typename std::enable_if<std::is_convertible<U, T>::value, U>::type> other)
: _foo(other.foo()) {}
};
int main() {
test<int> a;
test<long> b = a; // T = long, U = int
// true
std::cout << std::boolalpha << std::is_convertible<int, long>::value << std::endl;
return 0;
}
Если я просто объявляю первый шаблонный конструктор, код работает нормально. Со вторым конструктором, он не компилируется:
21:9: note: candidate template ignored: couldn't infer template argument 'U'
test(test<typename std::enable_if<std::is_convertible<U, T>::value, U>::type> other)
^
Почему не компилятор делать вывод U
в этом случае? Это выглядит довольно просто, я должен упустить что-то в выводе шаблона. Кроме того, если преобразование не может быть достигнуто таким образом, , что было бы лучшим способом сделать test<T>
конвертируемых в test<U>
?
Как примечание стороны, мне удалось получить его на работу, делая все test<T>
друзей, и объявить оператор преобразования, который использует enable_if
в реализации (как следует), но я все-таки хотел бы знать, почему первый, более простой подход не работает.
template <typename T>
class test {
int _foo;
template <typename U>
friend class test;
test(int foo) : _foo(foo) {}
public:
int foo() const { return _foo; }
test() : _foo(5) {}
template <typename U>
operator test<U>() const {
using return_t = typename std::enable_if<std::is_convertible<U, T>::value, U>::type;
return test<return_t>(_foo);
}
};
В некоторой степени важно: [Почему я должен избегать std :: enable_if в сигнатурах функций] (http://stackoverflow.com/questions/14600201/why-should-i-avoid-stdenable-if-in-function-signatures) , _ «Положить хак в параметры шаблона» _. – dfri