Reputation: 465
I want to add the arithmetic overload for std::vector
(probably not a very good idea but I want to use this as an example). I can implement it as the following
template <typename T, typename T2> auto& operator+=(std::vector<T>& a, const std::vector<T2>& b)
{
assert(a.size() == b.size());
std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::plus<>());
return a;
}
template <typename T, typename T2> auto operator+(const std::vector<T>& a,
const std::vector<T2>& b)
{
auto a0 = a;
return a0 += b;
}
template <typename T, typename T2> auto operator+(std::vector<T>&& a,
const std::vector<T2>& b)
{
auto a0 = a;
return a0 += b;
}
I need to write two function for operator+
in order to exploit the rvalue sementic in C++11. Is it possible to remove the duplicated code for operator+
?
Upvotes: 0
Views: 80
Reputation: 5624
you can use perfect-forwarding and possibly constrain via SFINAE, something like
template<typename T>
struct is_vector_addable: std::false_type {};
template<typename T>
struct is_vector_addable<std::vector<T>>: std::true_type {};
template <typename T, typename T2,typename E=
std::enable_if_t< is_vector_addable<std::decay_t<T>>::value >>
auto operator+( T&& a, const std::vector<T2>& b)
{
auto a0 = std::forward<T>(a);
return a0 += b;
}
as suggested by Sebastian Redl, you may also further constrain to std::vector's having addable elements ( in the sense of std::transform with std::plus semantics, this may or may not be what you really want ), in C++17:
template<typename T,typename T2,typename = void>
struct is_vector_addable: std::false_type {};
template<typename T,typename T2>
struct is_vector_addable<std::vector<T>,T2,std::void_t<
decltype( std::declval<T>() = std::declval<T>() + std::declval<T2>() )
>>: std::true_type {};
template <typename T, typename T2,typename E=std::enable_if_t< is_vector_addable<std::decay_t<T>,T2>::value >>
auto operator+( T&& a, const std::vector<T2>& b)
Upvotes: 4
Reputation: 217225
Whereas perfect forwarding is a solution in general case, an alternative is to pass by value:
template <typename T, typename T2>
auto operator+(std::vector<T> lhs, const std::vector<T2>& rhs)
{
return lhs += rhs;
}
Upvotes: 4