
On Fri, 12 Aug 2011 14:14:24 -0700, Jeremiah Willcock <jewillco@osl.iu.edu> wrote:
On Fri, 12 Aug 2011, Mostafa wrote:
On Fri, 12 Aug 2011 02:31:10 -0700, John Maddock <boost.regex@virgin.net> wrote:
From your description, I think I've done exactly this. E.g. --8<---------------cut here---------------start------------->8--- template <class U> struct X { // member function void f(int) becomes something like: template <class T> typename enable_if< mpl::and_< is_convertible<T,int> , some_condition_on<U> > >::type f(T x_) { int x = x_; ... } }; --8<---------------cut here---------------end--------------->8--- That works as long as the function has at least one parameter that can be turned into a template, but I have some cases that are operators or else have no parameters.
In case of no-parameter functions or operators, what's wrong with:
template <class U> struct T { void f() { f_impl(<static_cast<void *>(0)); }
private: template <class T> typename enable_if< mpl::and_< is_convertible<T, void *>, some_condition_on<U>
::type f_impl(T) { .... } };
In that case, f would not be covered by SFINAE, since it is not a template. Calls to f would fail because of the lack of f_impl,
Yes, I'm proposing moving the SFINAE failure one level deep to point where f_impl is called.
but that would be done after overload resolution.
I'm presuming you're talking about choosing between different multiple return types for no-parameter non-template member functions. For example, i) if template-parameter U is a class, we would want: CLASS * operator*(); ii) else: void * operator*(); In such a scenario wouldn't one just use a template-selector struct on the return type? The following example illustrates both scenarios, and it works on 4.0.1, #include <boost/utility/enable_if.hpp> #include <boost/mpl/logical.hpp> #include <boost/type_traits.hpp> #include <iostream> using namespace boost; struct CLASS {}; template <class U> struct T { void f() { this->f_impl(static_cast<void *>(0)); } void bar() { std::cout << "Non-class template parameter instantiations work." << std::endl; } struct deref { template <class R, class ENABLER = void> struct ret; template <class R> struct ret<R, typename enable_if<is_class<R> >::type > { typedef U * type; }; template <class R> struct ret<R, typename enable_if<mpl::not_<is_class<R> > >::type > { typedef void * type; }; }; typename deref::template ret<U>::type operator*() { return this->deref_impl(static_cast<void *>(0)); } private: template <class T> typename enable_if< mpl::and_< is_same<T, void *>, is_class<U> > >::type f_impl(T) { std::cout << "Class template parameter instantiations work." << std::endl; } template <class T> typename enable_if< mpl::and_< is_same<T, void *>, is_class<U> >, /*U **/typename deref::template ret<U>::type >::type deref_impl(T) { std::cout << "U * ret type." << std::endl; return 0; } template <class T> typename enable_if< mpl::and_< is_same<T, void *>, mpl::not_<is_class<U> > >, /*void **/typename deref::template ret<U>::type >::type deref_impl(T) { std::cout << "void * ret type." << std::endl; return 0; } }; int main() { T<CLASS> ins; ins.f(); *ins; T<int> ins2; ins2.bar(); *ins2; // ins2.f(); //Expected compiler error. return 0; } - Mostafa