【发布时间】:2016-12-12 21:35:17
【问题描述】:
我想创建一个模板类test<T>,如果T 可转换为U,我可以将其转换为test<U>(可能是隐式的)。我想到的最简单的想法是添加一个带有test<U> 的模板构造函数,其中模板参数U 由enable_if 控制。
#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);
}
};
【问题讨论】:
-
有点相关:Why should I avoid std::enable_if in function signatures,“将 hack 放入模板参数”。
标签: c++ templates constructor implicit-conversion sfinae