Re: trouble with SFNAE
On 6 Feb., 09:49, Brendan wrote:
I was trying out SFNAE techniques for the first time, and having some
trouble with it. Does anyone see what I'm doing wrong here?
[...]
template <class T>
struct has_iterator: enable_if<has_iterator_impl<T>::value, T>{};
template <class T>
void f(typename has_iterator<T>::type coll) {
}
struct iterable {
typedef int iterator;
};
int main(int argc, char* argv[]) {
iterable an_iterable;
f(an_iterable);
}
f(an_iterable) fails. It doesn't seem to match f. The strange thing is
I can declare an iterable object like this:
has_iterator<iterable>::type my_iterable;
Which makes me think that has_iterator is working correctly, but that
there's something wrong with f itself...
correct. f is a function template. And since you don't provide the
template parameter explicitly the compiler has to figure it out via
"template argument deduction". But
template <class T>
void f(typename has_iterator<T>::type coll);
actually has no "deducible context", so the compiler cannot figure out
what T is supposed to be. The reason os simple. You cannot expect a
compiler to find a T so that has_iterator<T>::type matches the
argument type. Since you can specialize class templates or 'type' may
not even depend on T there might not be a unique T so that it matches.
Instead, write this:
template <class T>
typename enable_if<
has_iterator_impl<T>::value
,void>::type f(T coll);
You'll be pleased to know that the upcoming C++ standard will let you
test many kinds of expressions with decltype for which SFINAE applies
as well, for example:
template<class C, class T>
inline auto find(C & c, T const& what) -> decltype(c.begin())
{
return std::find(c.begin(),c.end(),what);
}
If the compiler deduces C and C doesn't offer a begin member function,
this template will simply be ignored.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]