Skip to content

Instantly share code, notes, and snippets.

@wehu
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wehu/1987f716074904d26cf0 to your computer and use it in GitHub Desktop.
Save wehu/1987f716074904d26cf0 to your computer and use it in GitHub Desktop.
A solution for testing if a class has a method in c++
/*
* Copyright 2014 huwei04@hotmail.com. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef __HAS_FUNCTION_MEMBER_HPP__
#define __HAS_FUNCTION_MEMBER_HPP__
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
namespace has_function_member
{
namespace details
{
template <size_t c>
struct enable
{
typedef void type;
};
template <typename T>
struct wrapper
{
static T value;
};
template <typename T>
int result_check(T);
}
}
#define HAS_FUNCTION_MEMBER_PARAM(z, n, p) \
BOOST_PP_COMMA_IF(n) ::has_function_member::details::wrapper<p ## n>::value
#define HAS_FUNCTION_MEMBER_BASE(n, m, pn) \
namespace has_function_member \
{ \
template <typename T \
,typename R \
BOOST_PP_COMMA_IF(pn) \
BOOST_PP_ENUM_PARAMS(pn, typename P) \
,typename E=void> \
struct n ## _impl ## pn \
{ \
enum { value = false }; \
}; \
template <typename T \
BOOST_PP_COMMA_IF(pn) \
BOOST_PP_ENUM_PARAMS(pn, typename P) \
> \
struct n ## _impl ## pn<const T \
, void \
BOOST_PP_COMMA_IF(pn) \
BOOST_PP_ENUM_PARAMS(pn, P) \
, typename ::has_function_member::details::enable< \
sizeof(::has_function_member::details::wrapper<T>::value.m( \
BOOST_PP_REPEAT(pn, HAS_FUNCTION_MEMBER_PARAM, P)), 1) \
>::type> \
{ \
enum { value = true }; \
}; \
template <typename T \
,typename R \
BOOST_PP_COMMA_IF(pn) \
BOOST_PP_ENUM_PARAMS(pn, typename P) \
> \
struct n ## _impl ## pn<const T \
, R \
BOOST_PP_COMMA_IF(pn) \
BOOST_PP_ENUM_PARAMS(pn, P) \
, typename ::has_function_member::details::enable< \
sizeof(::has_function_member::details::result_check<R>( \
::has_function_member::details::wrapper<T>::value.m( \
BOOST_PP_REPEAT(pn, HAS_FUNCTION_MEMBER_PARAM, P)))) \
>::type> \
{ \
enum { value = true }; \
}; \
} \
template <typename T> struct n; \
template <typename T \
, typename R \
BOOST_PP_COMMA_IF(pn) \
BOOST_PP_ENUM_PARAMS(pn, typename P)> \
struct n<R(T::*)(BOOST_PP_ENUM_PARAMS(pn, P))> : has_function_member::n ## _impl ## pn \
< \
const typename boost::remove_pointer \
< \
typename boost::remove_cv<T>::type \
>::type \
, R \
BOOST_PP_COMMA_IF(pn) \
BOOST_PP_ENUM_PARAMS(pn, P) \
> {};
#define GEN_HAS_FUNCTION_MEMBER(z, n, m) \
HAS_FUNCTION_MEMBER_BASE(has_ ## m, m, n)
#define HAS_FUNCTION_MEMBER(m) \
BOOST_PP_REPEAT(10, GEN_HAS_FUNCTION_MEMBER, m)
#endif
#include "has_function_member.hpp"
#include <assert.h>
class Bar
{
public:
Bar(int);
};
class Foo
{
public:
Foo(int);
int foo(Bar);
};
HAS_FUNCTION_MEMBER(foo)
int main()
{
assert((!has_foo<void(Bar::*)(Bar)>::value));
assert((has_foo<int(Foo::*)(Bar)>::value));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment