------------------------------------------------------------ revno: 3141 committer: poy <p...@123gen.com> branch nick: trunk timestamp: Fri 2012-11-23 20:35:18 +0100 message: sfinae fix for VS modified: dcpp/Util.h test/testsfinae.cpp
-- lp:dcplusplus https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk Your team Dcplusplus-team is subscribed to branch lp:dcplusplus. To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/Util.h' --- dcpp/Util.h 2012-11-10 15:15:22 +0000 +++ dcpp/Util.h 2012-11-23 19:35:18 +0000 @@ -92,29 +92,20 @@ template<typename T> double fraction(T a, T b) { return static_cast<double>(a) / b; } /** Uses SFINAE to determine whether a type provides a function; stores the result in "value". -Inspired by <http://stackoverflow.com/a/8752988>. */ -#ifndef _MSC_VER -#define HAS_FUNC(name, funcRet, funcTest) \ - template<typename HAS_FUNC_T> struct name { \ - typedef char yes[1]; \ - typedef char no[2]; \ - template<typename HAS_FUNC_U> static yes& check(HAS_FUNC_U* data, \ - typename std::enable_if<std::is_same<funcRet, decltype(data->funcTest)>::value>::type* = nullptr); \ - template<typename> static no& check(...); \ - static const bool value = sizeof(check<HAS_FUNC_T>(nullptr)) == sizeof(yes); \ - } -#else -/// @todo don't verify the return type of the function on MSVC as it fails for obscure reasons. recheck later... -#define HAS_FUNC(name, funcRet, funcTest) \ - template<typename HAS_FUNC_T> struct name { \ - typedef char yes[1]; \ - typedef char no[2]; \ - template<typename HAS_FUNC_U> static yes& check(HAS_FUNC_U* data, \ - decltype(data->funcTest)* = nullptr); \ - template<typename> static no& check(...); \ - static const bool value = sizeof(check<HAS_FUNC_T>(nullptr)) == sizeof(yes); \ - } -#endif +Inspired by <http://stackoverflow.com/a/8752988>. +Note that checkRet & check could be merged into 1 function, but VS 11 doesn't like having a +decltype inside that enable_if; so the 2 checks are separate. */ +#define HAS_FUNC(name, funcRet, funcTest) \ + template<typename HAS_FUNC_T> struct name { \ + typedef char yes[1]; \ + typedef char no[2]; \ + template<typename HAS_FUNC_V> static void checkRet( \ + typename std::enable_if<std::is_same<funcRet, HAS_FUNC_V>::value>::type*); \ + template<typename HAS_FUNC_U> static yes& check( \ + decltype(checkRet<decltype(std::declval<HAS_FUNC_U>().funcTest)>(nullptr))*); \ + template<typename> static no& check(...); \ + static const bool value = sizeof(check<HAS_FUNC_T>(nullptr)) == sizeof(yes); \ + } class Util { === modified file 'test/testsfinae.cpp' --- test/testsfinae.cpp 2012-11-10 15:40:59 +0000 +++ test/testsfinae.cpp 2012-11-23 19:35:18 +0000 @@ -6,11 +6,16 @@ using namespace dcpp; -struct Funcs { +struct Base { + void fbase1() { } +}; + +struct Funcs : Base { void f1() { } void f2(int) { } int f3() { return 0; } void f4(const string&) { } + void f5(string&) { } }; template<typename T> @@ -20,6 +25,8 @@ HAS_FUNC(F2, void, f2(0)); HAS_FUNC(F3, int, f3()); HAS_FUNC(F4, void, f4(string())); + HAS_FUNC(F5, void, f5(std::function<string&()>()())); + HAS_FUNC(F6, void, fbase1()); // these should be false. HAS_FUNC(FN1, void, lol()); @@ -30,6 +37,8 @@ bool test_F2() { return F2<T>::value; } bool test_F3() { return F3<T>::value; } bool test_F4() { return F4<T>::value; } + bool test_F5() { return F5<T>::value; } + bool test_F6() { return F6<T>::value; } bool test_FN1() { return FN1<T>::value; } bool test_FN2() { return FN2<T>::value; } @@ -51,14 +60,12 @@ ASSERT_EQ(true, x.test_F2()); ASSERT_EQ(true, x.test_F3()); ASSERT_EQ(true, x.test_F4()); + ASSERT_EQ(true, x.test_F5()); + ASSERT_EQ(true, x.test_F6()); ASSERT_EQ(false, x.test_FN1()); -#ifndef _MSC_VER - /* TODO these tests ensure that the return value of the tested function is correctly validated. - doesn't work in MSVC, as explained by the definition of HAS_FUNC. */ ASSERT_EQ(false, x.test_FN2()); ASSERT_EQ(false, x.test_FN3()); -#endif ASSERT_EQ(true, x.i()); }
_______________________________________________ Mailing list: https://launchpad.net/~linuxdcpp-team Post to : linuxdcpp-team@lists.launchpad.net Unsubscribe : https://launchpad.net/~linuxdcpp-team More help : https://help.launchpad.net/ListHelp