我已经创建了模板化结构,并正在尝试重载二进制运算符。由于某种原因,即使该类型正确地插入了两者之间,该函数也不会返回正确的数据类型。
template<typename T>
struct Number{
const T value;
Number(T a) : value(a) {}
template<typename U>
auto operator*(Number<U> other){
auto new_value = value*other.value;
std::cout << typeid(new_value).name() << std::endl;
return Number(new_value);
}
};
现在,如果我使用main中调用的以下代码执行此操作。它返回第一个类型的Number,而不是较高类型的Number。
auto b = Number<int>(6) * Number<double>(2.3); // this should be an int*double=double
std::cout << b.value << typeid(b.value).name() << std::endl;
auto c = Number<double>(2.3) * Number<int>(6);
std::cout << c.value << typeid(c.value).name() << std::endl;
输出如下: d 13i d 13.8d
据我了解,当函数返回新的Number(new_value)
时,将调用不正确的构造函数。我不了解这种情况的发生方式和原因,因为new_value属于“正确类型”。
答案 0 :(得分:9)
在模板范围内,模板名称将代表所注入的类名,而不是模板。因此不会有CTAD,and that's by design
使用return Number<decltype(new_value)>(new_value);
是简单的解决方法。
答案 1 :(得分:1)
您将返回第一种而不是第二种:
template<typename U>
auto operator*(Number<U> other){
auto new_value = value*other.value;
std::cout << typeid(new_value).name() << std::endl;
return Number(new_value);
}
即使new_value
是双精度数,您也将其存储在Number<T>
中。
尝试:
template<typename U>
auto operator*(Number<U> other){
auto new_value = value*other.value;
std::cout << typeid(new_value).name() << std::endl;
return Number<decltype(new_value)>(new_value);
}
答案 2 :(得分:0)
StoryTeller指出,在类模板定义中,类的名称是指特定的类实例(称为 injected-class-name ),而不是名称模板。
但是,如果您希望类模板自变量的推论仍然适用,则可以限定名称:
return ::Number(new_value);
::Number
是指类模板Number
,而不是特定类型Number<T>
。但这对于其他阅读您的代码的人来说可能太神奇了,并且简单地使用Number<decltype(new_value)>(new_value)
会有很多好处。