template<typename type>
using point = std::pair<type, type>;
template<typename type>
point<type> operator-(point<type> a, point<type> b)
{
return{ a.first - b.first, a.second - b.second };
}
int main() {
point<float> a = { 0, 0 };
point<int> b = { 1, 2 };
point<float> p = a - b; // This does not compile.
return 0;
}
如何将point float和point int参数传递给我的“ - ”运算符,并将point int参数隐式转换为point float类型?
当然,我可以将该点声明为一个类,并使用构造函数来实现这一点。但这对我来说似乎很啰嗦。
答案 0 :(得分:3)
注意:最初问题没有提及operator-
,只是询问是否可以自动将point<int>
转换为point<float>
而不是类。我的回答解决了这个问题。我会留待它参考。 Colin Pitrat的答案解决了问题,因为它目前的表现更好。
已为您定义:std::pair
有一个通用复制构造函数(即允许在可转换模板参数之间进行隐式转换的构造函数)
template< class U1, class U2 >
pair( const pair<U1, U2>& p );
(自{C ++ 14起为constexpr
),只要pair<T1, U1>
隐式转换为pair<T2, U2>
,就允许使用T2
初始化T1
}和U2
到U1
:
4)使用
first
初始化p.first
,使用second
初始化p.second
。 (source)
这意味着以下代码运行良好:
template<typename type>
using point = std::pair<type, type>;
float dist(point<float> a, point<float> b)
{
return pow(pow(a.first-b.first, 2) + pow(a.second - b.second, 2), 0.5);
}
int main() {
std::cout << dist(point<int>{ 0, 0 }, point<int>{ 1, 1 });
return 0;
}
答案 1 :(得分:2)
我认为您的operator-
实际上是这样写的(使用type
而不是float
以及使用first
和second
代替x
}和y
:
template<typename type>
point<type> operator-(point<type> a, point<type> b)
{
return{ a.first - b.first, a.second - b.second };
}
CompuChip在他的回答中谈到generalized copy constructor
并不适合你的原因是编译器需要找出要实例化的函数,并且你用{{{{}来调用它。 1}}和point<float>
有两个不同的point<int>
。
只有在首先找到匹配函数时才会查找将type
转换为point<int>
的通用复制构造函数(例如,如果存在非模板point<float>
)。但这只是在找到匹配函数之后,因此在模板实例化之后,为时已晚!
对于常规类,您需要做的是定义与模板相关的函数,这些函数支持在类模板中作为朋友的所有参数的隐式类型转换。 (参见Scott Meyer的优秀着作&#34; Effective C ++&#34;第46页)
但是,在您使用operator-(point<float>, point<float>)
的情况下,您无法执行此操作。
一个选项是使用两个模板参数定义std::pair
,如下所示:
operator-
它的作用是定义一个运算符,它取两个不同模板参数的点并返回一个与template<typename t1, typename t2>
auto operator-(point<t1> a, point<t2> b) -> point<decltype(a.first - b.first)>
{
return{ a.first - b.first, a.second - b.second };
}
相对应的类型的点,这将是&#34; natural&#34;一个你期待的。