我对模板有一个奇怪的问题,我试图在它们之间做一个基本的补充 模板类和" float / double / int"类型。这是非常基本的,但如果我这样做:
template<class T>
class toto{
T a;
};
template<class T>
toto<T> operator+(toto<T> const&, T&){
std::cout << "hello " <<std::endl;
}
int main(){
toto<float> t;
toto<float> d = t +2.3;
}
它不会编译,因为2.3被认为是双精度,它与签名不匹配。我可以为我的operator +使用第二个模板参数
template<class T, class D>
toto<T> operator+(toto<T> const&, D&){
std::cout << "hello " <<std::endl;
}
它编译,执行正确,但太危险D可以是一切。另一种方法是使用float,double或int(O_O)创建不同的签名。 Boost :: enable_if似乎是我的解决方案,但在我阅读的文档中:
template <class T>
T foo(T t,typename enable_if<boost::is_arithmetic<T> >::type* dummy = 0);
将此方法应用于运算符* doest不起作用,因为编译器抱怨默认参数是被禁止的。
有什么建议吗?
干杯,
++吨
答案 0 :(得分:5)
对第二个参数使用非推导的上下文。并const
- 引用作为参数,以允许rvalues。
template <typename T> struct identity {using type = T;};
template <typename T>
using identity_t = typename identity<T>::type;
template<class T>
toto<T> operator+(toto<T> const&, identity_t<T> const&)
{
std::cout << "hello " <<std::endl;
}
非推导的上下文将导致推导忽略某个参数的调用参数,因为无法推导出调用的模板参数。在某些情况下,如此处所希望的那样,因为不再存在不一致的推论。换句话说,第二个参数的类型完全取决于调用的第一个参数,而不是第二个参数(可以隐式转换)。
toto<float> d = t + 2.3;
现在应该编译,Demo。
答案 1 :(得分:1)
您可以像这样使用enable_if
:
template<class T, class D, typename = typename std::enable_if<std::is_arithmetic<D>::value>::type>
toto<T> operator+(toto<T> const&, const D&){
std::cout << "hello " <<std::endl;
return toto<T>();
}
答案 2 :(得分:1)
enable_if
s看起来不太漂亮,但其他方法感觉更糟。
我通常使用返回值类型来启用函数,因为它位于最多位置
在前面:
#include<type_traits>
#include<iostream>
template<class T>
class toto
{
T a;
};
template<typename T,typename D>
typename std::enable_if< std::is_arithmetic<D>::value
// && some other constraint
// && etc.
, toto<T> >::type operator+(toto<T> const&, D const&)
{
std::cout << "hello " <<std::endl;
}
int main()
{
toto<float> t;
toto<float> d = t +2.3;
}