Reputation: 161
I have the following 2 function overloads:
template<typename F, typename T>
void func(F f, std::vector<T>& v) { ... }
template<typename F, typename T>
void func(F f, const std::vector<T>& v) { ... }
The body of both of them is the same. Is there an easy way to define them both with a single definition to avoid code duplication using C++17 or earlier standard?
Just to clarify, I want the functions to be constrained based on the std::vector
part but I want to allow const and non-const references to be passed.
The reason I need both overloads is that the F
function object will be applied to the vector and sometimes F
will modify the vector and sometimes it will only observe the vector (and I want to allow the vector to be declared const
in the second case).
I guess I can use C++20 concepts to constrain the function template parameter but I was wondering if there's an easy way to achieve the same thing using C++17 or earlier version of the standard.
Upvotes: 0
Views: 120
Reputation: 161
I found another solution but it still adds a little bit of overhead:
template<typename F, typename VecT>
auto func_vec(F f, VecT& vec)
{
//actual code
}
template<typename F, typename T>
auto func(F f, std::vector<T>& vec) { return func_vec(f, vec); }
template<typename F, typename T>
auto func(F f, const std::vector<T>& vec) { return func_vec(f, vec); }
A third function is defined (func_vec
) which holds the actual implementation of func
.
Note that typename VecT
can accept both const
and non-const
arguments.
func
overloads are just used to constrain the argument to be of type std::vector<T>&
with or without a const
qualifier.
The good thing about this solution is that it doesn't use SFINAE and is fairly easy to read. The bad thing is that you have to introduce another function template for the actual implementation.
Upvotes: 0
Reputation: 10591
you don't need require
clause to do sfinae,
#include <vector>
#include <type_traits>
template<typename T>
struct is_vector : std::false_type{};
template<typename ...Args>
struct is_vector<std::vector<Args...>> : std::true_type{};
template<
typename F,
typename C,
std::enable_if_t<is_vector<std::remove_cvref_t<C>>::value,std::nullptr_t> = nullptr
>
void func(F f, C&& v) {
// ...
}
* std::remove_cvref_t
is still c++20, you need to use std::remove_cv_t<std::remove_reference_t<T>>
in earlier standard
Upvotes: 1