I have two functions, which accept variadic template, and second that accepts std::vector<std::string>. Is it possible, to override variadic templated function without additional arguments? I tried a few things, but it didn't work.
template <typename ... Args>
std::string Func(std::string, Args && ...);
template <typename ArgType = std::string, typename Alloc>
std::string Func(std::string, const std::vector<ArgType, Alloc> &);
int main()
{
std::vector<std::string> v;
Func("asd", 1, 2.0f);
Func("asd", v);
}
Always function with variadic template pack is called. Is the compiler really can't determine the vector specialization? Thanks
Is the compiler really can't determine the vector specialization?
Yes it can, but it would require a conversion to const std::vector<ArgType, Alloc>&
so the first one that doesn't require any conversion is selected instead. If you remove the const
part it would select the second version.
You could create a type trait to disqualify the first function if the type is some sort of vector
though.
Example:
template<class... Ts>
struct is_first_a_vector {
static std::false_type test(...); // matches anything
// this matches only if the first argument is a `vector` of some sort:
template<template<class,class> class C, class T, class A, class... Rest>
static auto test(C<T,A>&&, Rest&&...) ->
std::enable_if_t<std::is_same_v<C<T,A>, std::vector<T,A>>, std::true_type>;
static constexpr bool value =
decltype(test(std::declval<std::remove_cvref_t<Ts>>()...))::value;
};
Alternatively:
template <class...>
struct is_first_a_vector_impl : std::false_type {};
template <class T, class A, class... Ts>
struct is_first_a_vector_impl<std::vector<T, A>, Ts...> : std::true_type {};
template <class... Ts>
struct is_first_a_vector
: is_first_a_vector_impl<std::remove_cv_t<std::remove_reference_t<Ts>>...> {};
Plus a helper that works with both type traits above:
template<class... Ts>
inline constexpr bool is_first_a_vector_v = is_first_a_vector<Ts...>::value;
And here's the type trait used to enable the first function only if the first argument after the std::string
is not a vector
of some sort:
template <typename... Args>
std::enable_if_t<!is_first_a_vector_v<Args...>, std::string> // <-
Func(std::string, Args&&...);
template <typename ArgType = std::string, typename Alloc>
std::string Func(std::string, const std::vector<ArgType, Alloc> &);
Demo using version 1 and Demo using version 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With