r256534 - [TrailingObjects] Use a different technique to determine if a getDecl
James Y Knight via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 28 20:34:11 PST 2015
Author: jyknight
Date: Mon Dec 28 22:34:11 2015
New Revision: 256534
URL: http://llvm.org/viewvc/llvm-project?rev=256534&view=rev
Log:
[TrailingObjects] Use a different technique to determine if a getDecl
member function exists on a class.
The previous trick depended on inheriting from the class it was
checking, which will fail when I start marking things 'final'.
Hopefully this actually builds with all supported compilers...
Modified:
cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=256534&r1=256533&r2=256534&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Mon Dec 28 22:34:11 2015
@@ -558,22 +558,19 @@ bool matchesFirstInPointerRange(const Ma
return false;
}
-/// \brief Metafunction to determine if type T has a member called getDecl.
-template <typename T> struct has_getDecl {
- struct Default { int getDecl; };
- struct Derived : T, Default { };
-
- template<typename C, C> struct CheckT;
-
- // If T::getDecl exists, an ambiguity arises and CheckT will
- // not be instantiable. This makes f(...) the only available
- // overload.
- template<typename C>
- static char (&f(CheckT<int Default::*, &C::getDecl>*))[1];
- template<typename C> static char (&f(...))[2];
-
- static bool const value = sizeof(f<Derived>(nullptr)) == 2;
-};
+/// Metafunction to determine if type T has a member called
+/// getDecl.
+///
+/// There is a default template inheriting from "false_type". Then, a
+/// partial specialization inherits from "true_type". However, this
+/// specialization will only exist when the call to getDecl() isn't an
+/// error -- it vanishes by SFINAE when the member doesn't exist.
+template <typename> struct type_sink_to_void { typedef void type; };
+template <typename T, typename = void> struct has_getDecl : std::false_type {};
+template <typename T>
+struct has_getDecl<
+ T, typename type_sink_to_void<decltype(std::declval<T>().getDecl())>::type>
+ : std::true_type {};
/// \brief Matches overloaded operators with a specific name.
///
More information about the cfe-commits
mailing list