From: Andy Venikov on 20 May 2010 12:33 Johannes Schaub (litb) wrote: <snip> >> > > No. instantiation of "enable_if<false, type>" doesn't fail. It's the access > to "::type", which happens during deduction at the very toplevel, which > fails. Still not clear. The way I understand it now, is that if the error happens while trying to instantiate a class during template argument deduction, then SFINAE kicks in. As in if the statement that generates an error is not in the body of the class but in <...> of the template specialization, then it's OK. I re-organized my original example with this in mind. And I got some surprising results. It compiles on both gcc 4.4 and on Comeau online. But I get different result. Gcc is able to tell the difference and has_foo<...>::value is true only for the types that have function foo. Comeau always returns false. Now I wander what compiler is right? Here's the re-worked example: (the idea was to move sizeof(&T::foo) from within class body to class declaration> -----> Code start typedef unsigned int size_t; template <bool Test, typename T = void> struct enable_if; template <typename T> struct enable_if<true, T> { typedef T type; static const bool value = true; }; template <typename T, typename Enable = void> struct has_foo { static const bool value = false; }; template <typename T, typename Enable = void> struct take_address_of_foo { static const bool value = false; }; template <typename T> struct take_address_of_foo<T, typename enable_if<0 < sizeof(decltype(&T::foo))>::type> { static const bool value = true; }; template <typename T> struct has_foo<T, typename enable_if<take_address_of_foo<T>::value>::type> { static const bool value = true; }; struct WithFoo { int foo(int, int, int); }; struct NoFoo { }; template <typename T, bool HasFoo = T::value> struct CompileError { typedef typename T::non_existing_type_brrr type; }; //All lines compile fine. But Comeau alway returns false. //Gcc returns true for the "WithFoo" case const bool B1 = has_foo<WithFoo>::value; const bool B2 = has_foo<NoFoo>::value; const bool B3 = has_foo<int>::value; <-------- Code end Thanks, Andy. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Andy Venikov on 25 May 2010 03:56 Andy Venikov wrote: <snip> Sorry to re-post my question, but I think the question got lost in between the lines. The following code compiles fine on both gcc 4.3 and Comeau online (with and without C++0x support) but produces different results. Gcc returns what I'd expect (true if T has foo and false if it doesn't) Comeau always returns false. I wonder, who's right? typedef unsigned int size_t; template <bool Test, typename T = void> struct enable_if; template <typename T> struct enable_if<true, T> { typedef T type; static const bool value = true; }; template <typename T, typename Enable = void> struct has_foo { static const bool value = false; }; template <typename T, typename Enable = void> struct take_address_of_foo { static const bool value = false; }; template <typename T> struct take_address_of_foo<T, typename enable_if<0 < sizeof(&T::foo)>::type> { static const bool value = true; }; template <typename T> struct has_foo<T, typename enable_if<take_address_of_foo<T>::value>::type> { static const bool value = true; }; struct WithFoo { int foo(int, int, int); }; struct NoFoo { }; template <typename T, bool HasFoo = T::value> struct CompileError { typedef typename T::non_existing_type_brrr type; }; //Force compile-error to show the results of has_foo<...>::type //Comeau alway returns false. //Gcc returns true for the "WithFoo" case typedef CompileError<WithFoo, has_foo<WithFoo>::value>::type T1; typedef CompileError<NoFoo, has_foo<NoFoo>::value>::type T2; typedef CompileError<int, has_foo<int>::value>::type T3; > Thanks, > Andy. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Mathias Gaunard on 26 May 2010 17:35 On 12 mai, 09:07, Andy Venikov <swojchelo...(a)gmail.com> wrote: > > For example, try implementing has_foo<> by taking an address of foo. If foo exists, everything fine. If foo doesn't exist, then you'll get compile-time error no matter what. It is well-known how to do this, consult the relevant articles. In C++0x, you can do even better though, you can test any expression, which allows to take into account conversions and object constness automatically. > > Code: > > template <bool Test, typename T = void> > struct enable_if; > > template <typename T> > struct enable_if<true, T> > { > typedef T type; > static const bool value = true; > > }; > > template <typename T, typename Enable = void> > struct has_foo > { > static const bool value = false; > > }; > > template <typename T> > struct take_address_of_foo > { > static const size_t nTest = sizeof(&T::foo); > static const bool value = enable_if<nTest>::value; > > }; > > template <typename T> > struct has_foo<T, typename enable_if<take_address_of_foo<T>::value>::type> > { > static const bool value = true; > > }; You're doing it wrong, this doesn't test for T::foo in an SFINAE context. Here is an example of how to do it. template<typename T> struct has_foo { private: struct found {}; struct not_found { char two[2]; }; template<typename X, int (X::*)(int, int, int)> struct member {}; template<typename X> static found test(member<X, &X::foo>*); template<typename X> static not_found test(...); public: static const bool value = sizeof(test<T>(0)) == sizeof(found); typedef boost::mpl::bool_<value> type; }; -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Ilya Sokolov on 27 May 2010 03:35 Mathias Gaunard wrote: > On 12 mai, 09:07, Andy Venikov <swojchelo...(a)gmail.com> wrote: >> For example, try implementing has_foo<> by taking an address of foo. >> If foo exists, everything fine. If foo doesn't exist, then you'll >> get compile-time error no matter what. > > It is well-known how to do this, consult the relevant articles. > In C++0x, you can do even better though, you can test any expression, > which allows to take into account conversions and object constness > automatically. "Solving the SFINAE problem for expressions" http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html > [snip] > > template<typename T> > struct has_foo > { > private: > struct found {}; > struct not_found { char two[2]; }; > > template<typename X, int (X::*)(int, int, int)> > struct member {}; > > template<typename X> > static found test(member<X, &X::foo>*); > > template<typename X> > static not_found test(...); > > public: > static const bool value = sizeof(test<T>(0)) == sizeof(found); > typedef boost::mpl::bool_<value> type; > }; Is it required by the standard that sizeof(found) != sizeof(not_found)? -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Ilya Sokolov on 27 May 2010 03:35 Andy Venikov wrote: > Andy Venikov wrote: > <snip> > > Sorry to re-post my question, but I think the question got lost in > between the lines. > > The following code compiles fine on both gcc 4.3 and Comeau online (with > and without C++0x support) but produces different results. Gcc returns > what I'd expect (true if T has foo and false if it doesn't) Comeau > always returns false. > > I wonder, who's right? I don't see anything in the standard that prevents Comeau from matching partial specialization of task_address_of_foo. > [snip] Shorter variant would be: template <bool Test, typename T = void> struct enable_if; template <typename T> struct enable_if<true, T> { typedef T type; static const bool value = true; }; template <typename T, typename Enable = void> struct has_foo { static const bool value = false; }; template <typename T> struct has_foo<T, typename enable_if<sizeof(&T::foo)>::type> { static const bool value = true; }; or: template<int> struct void_ { typedef void type; }; template <typename T, typename Enable = void> struct has_foo { static const bool value = false; }; template <typename T> struct has_foo<T, typename void_<sizeof(&T::foo)>::type> { static const bool value = true; }; or using cpp0x: template <typename T, typename Enable = void> struct has_foo { static const bool value = false; }; template <typename T> struct has_foo<T, decltype(T::foo)> { static const bool value = true; }; Sadly, for all variants has_foo<WithFoo>::value == false in como. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 Prev: Does covariant return types hold for non-virtual? Next: C++ Passion = Madness |