Re: how to prefer one template function over the other
On 2011-05-25 02:28, Brendan Miller wrote:
I have these two template functions and a related utility type:
template <typename Dummy, typename T>
struct second_type {
typedef T type;
};
template <typename T>
bool is_back_insertion_seq() {
return false;
}
// Using SFINAE to disable this function for non-back-insertion
// sequences.
template <typename T>
typename second_type<
decltype(T().push_back(
typename iterator_traits<decltype(
T().begin())>::value_type())),
bool>::type
is_back_insertion_seq() {
return true;
}
If I call is_back_insertion_seq<vector<int> >() I want the second form
to be called.
However, actually when I call is_back_insertion_seq<vector<int> >(), the
compiler errors out, as the call is ambiguous.
Is there a trick to make one overload preferable to the other if the two
are ambiguous?
Sure. One way to realize that is to add different function parameters
and a call expression with some argument such that one overload would be
preferred. Here is an example that uses this technique:
#include <type_traits>
#include <iterator>
template<class T>
struct is_back_insertion_seq_trait_impl
{
template<class U,
class = decltype(U().push_back(
typename std::iterator_traits<decltype(
U().begin())>::value_type()))
>
static std::true_type test(int);
template<class>
static std::false_type test(...);
typedef decltype(is_back_insertion_seq_trait_impl::test<T>(0)) type;
};
template<class T>
struct is_back_insertion_seq_trait :
is_back_insertion_seq_trait_impl<T>::type
{
};
template <typename T>
typename std::enable_if<!is_back_insertion_seq_trait<T>::value, bool>::type
is_back_insertion_seq() {
return false;
}
template <typename T>
typename std::enable_if<is_back_insertion_seq_trait<T>::value, bool>::type
is_back_insertion_seq() {
return true;
}
You may notice that within is_back_insertion_seq_trait_impl the two test
functions are provided. The second overload is less preferred compared
to the second one in overload resolution. Technically this is so,
because a standard conversion sequence is a better conversion sequence
than an ellipsis conversion sequence ([over.ics.rank]).
Let me add that I suggest to use std::declval instead of
value-initialization in your decltype usage, because there does not
exist a fundamental requirement, that a back insertion sequence is
default-constructible.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]