嵌套向量不遵循提升规则。解决方案有一个错误。
Nested vectors do not follow promotion rules. Solution has a bug.
此程序添加了嵌套向量,但没有正确提升类型。我认为 std::plus 需要根据基本类型提升规则接受 T1 或 T2。原来的问题就在这个post()。
main.cpp
#include <algorithm>
#include <iostream>
#include <vector>
template<typename T1>
std::ostream& operator<<(std::ostream& stream, std::vector<T1> r){
if(r.size() == 0){
return stream;
}
else{
stream << "(";
for(int i = 0; i < r.size(); i++){
if(i < (r.size() - 1)){
stream << r[i] << ", ";
}
else{
stream << r[i] << ")";
}
}
}
return stream;
};
template <typename T1, typename T2>
struct Add : std::plus<T1> { };//<-Here T1 or T2 depending on their types.
template <typename T1, typename T2>
struct Add<std::vector<T1>, std::vector<T2>>
{
auto operator()(const std::vector<T1>& l, const std::vector<T2>& r)
-> std::vector<decltype(Add<T1,T2>{}(l[0], r[0]))>
{
using type = decltype(Add<T1,T2>{}(l[0], r[0]));
std::vector<type> ans;
if(l.size() == std::max(l.size(),r.size()))
std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans), Add<T1,T2>{});
else
std::transform(l.begin(), l.end(), r.begin(), std::back_inserter(ans), Add<T1,T2>{});
return ans;
};
};
template <typename T1, typename T2>
auto operator+(const std::vector<T1>& lhs, const std::vector<T2>& rhs)
-> decltype(Add<std::vector<T1>, std::vector<T2>>{}(lhs, rhs))
{
return Add<std::vector<T1>, std::vector<T2>>{}(lhs, rhs);
}
int main(){
std::vector<int> e = {1};
std::vector<double> q = {1.5};
//Incorrect result = 2
std::cout << (e + q) << std::endl;
//Correct result = 2.5
std::cout << (q + e) << std::endl;
return 0;
}
定义主模板时使用std::common_type
Add<>
,像这样(必须#include <type_traits>
):
template <typename T1, typename T2>
struct Add : std::plus<typename std::common_type<T1,T2>::type> { };//<-Here T1 or T2 depending on their types.
您基本上告诉 Add
主模板使用 "best" 类型。然后专业化将使用主要的,而后者现在负责提升。
您的代码中有两个问题(我对您的原始问题的回答有误)。第一个,正如 is using std::common_type
提到的基本情况。
第二个是一个简单的错误。考虑这个 if 语句:
if(l.size() == std::max(l.size(),r.size()))
std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans),
Add<T1,T2>{});
else
std::transform(l.begin(), l.end(), r.begin(), std::back_inserter(ans),
Add<T1,T2>{});
Add<T1,T2>::operator()
,在偏特化的情况下,有两个参数:一个std::vector<T1>
和一个std::vector<T2>
,顺序为。但是在 if
语句的两个分支中,我们实际上是以不同的顺序调用它们。在 true
分支中,我们以相反的顺序调用它们,因此只需反转模板中的顺序即可:
if(l.size() == std::max(l.size(),r.size()))
std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans),
Add<T2,T1>{});
实际上应该完全删除 if
-语句,以便现在的专业化案例是:
template <typename T1, typename T2>
struct Add<std::vector<T1>, std::vector<T2>>
{
using R = decltype(Add<T1,T2>{}(std::declval<T1>(), std::declval<T2>()));
std::vector<R> operator()(const std::vector<T1>& l, const std::vector<T2>& r)
{
std::vector<R> ans;
std::transform(l.begin(),
l.begin() + std::min(l.size(), r.size()),
r.begin(),
std::back_inserter(ans),
Add<T1,T2>{});
return ans;
};
};
此程序添加了嵌套向量,但没有正确提升类型。我认为 std::plus 需要根据基本类型提升规则接受 T1 或 T2。原来的问题就在这个post(
main.cpp
#include <algorithm>
#include <iostream>
#include <vector>
template<typename T1>
std::ostream& operator<<(std::ostream& stream, std::vector<T1> r){
if(r.size() == 0){
return stream;
}
else{
stream << "(";
for(int i = 0; i < r.size(); i++){
if(i < (r.size() - 1)){
stream << r[i] << ", ";
}
else{
stream << r[i] << ")";
}
}
}
return stream;
};
template <typename T1, typename T2>
struct Add : std::plus<T1> { };//<-Here T1 or T2 depending on their types.
template <typename T1, typename T2>
struct Add<std::vector<T1>, std::vector<T2>>
{
auto operator()(const std::vector<T1>& l, const std::vector<T2>& r)
-> std::vector<decltype(Add<T1,T2>{}(l[0], r[0]))>
{
using type = decltype(Add<T1,T2>{}(l[0], r[0]));
std::vector<type> ans;
if(l.size() == std::max(l.size(),r.size()))
std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans), Add<T1,T2>{});
else
std::transform(l.begin(), l.end(), r.begin(), std::back_inserter(ans), Add<T1,T2>{});
return ans;
};
};
template <typename T1, typename T2>
auto operator+(const std::vector<T1>& lhs, const std::vector<T2>& rhs)
-> decltype(Add<std::vector<T1>, std::vector<T2>>{}(lhs, rhs))
{
return Add<std::vector<T1>, std::vector<T2>>{}(lhs, rhs);
}
int main(){
std::vector<int> e = {1};
std::vector<double> q = {1.5};
//Incorrect result = 2
std::cout << (e + q) << std::endl;
//Correct result = 2.5
std::cout << (q + e) << std::endl;
return 0;
}
定义主模板时使用std::common_type
Add<>
,像这样(必须#include <type_traits>
):
template <typename T1, typename T2>
struct Add : std::plus<typename std::common_type<T1,T2>::type> { };//<-Here T1 or T2 depending on their types.
您基本上告诉 Add
主模板使用 "best" 类型。然后专业化将使用主要的,而后者现在负责提升。
您的代码中有两个问题(我对您的原始问题的回答有误)。第一个,正如 std::common_type
提到的基本情况。
第二个是一个简单的错误。考虑这个 if 语句:
if(l.size() == std::max(l.size(),r.size()))
std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans),
Add<T1,T2>{});
else
std::transform(l.begin(), l.end(), r.begin(), std::back_inserter(ans),
Add<T1,T2>{});
Add<T1,T2>::operator()
,在偏特化的情况下,有两个参数:一个std::vector<T1>
和一个std::vector<T2>
,顺序为。但是在 if
语句的两个分支中,我们实际上是以不同的顺序调用它们。在 true
分支中,我们以相反的顺序调用它们,因此只需反转模板中的顺序即可:
if(l.size() == std::max(l.size(),r.size()))
std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans),
Add<T2,T1>{});
实际上应该完全删除 if
-语句,以便现在的专业化案例是:
template <typename T1, typename T2>
struct Add<std::vector<T1>, std::vector<T2>>
{
using R = decltype(Add<T1,T2>{}(std::declval<T1>(), std::declval<T2>()));
std::vector<R> operator()(const std::vector<T1>& l, const std::vector<T2>& r)
{
std::vector<R> ans;
std::transform(l.begin(),
l.begin() + std::min(l.size(), r.size()),
r.begin(),
std::back_inserter(ans),
Add<T1,T2>{});
return ans;
};
};