如何查找特定原型的方法是否存在于类中? [英] How to find if a method of a particular prototype exists inside a class?

查看:119
本文介绍了如何查找特定原型的方法是否存在于类中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一些SFINAE功能;当前在必须在Linux和Windows中运行的应用程序的一部分中;编译器选择是用于Windows应用程序的MSVC(Visual Studio 2010 10.0)和用于Linux应用程序的GCC 4.4.5。



我必须检查一些给定的对象是否提供了一些函数执行自定义序列化并调用此函数,或者执行一个简单的 memcpy sizeof(Object)



问题是,一段代码在MSVC中编译时没有警告或错误,但是在使用GCC编译时,代码如下:

 模板
<
typename类型,
typename返回,
typename参数,
返回(Type :: * Pointer)(参数)const
> struct sMemberMethodConst {};

模板
<
typename类型,
typename返回,
typename参数,
返回(Type :: *)(参数)
> struct sMemberMethod {};

template< typename T> struct sMemberMethodChecker
{
template< typename Type> static char HasCustomSizeMethod(sMemberMethodConst< Type,size_t,void,& Type :: Size> *);
template< typename Type> static long HasCustomSizeMethod(...);
template< typename Type> static char HasSerializeMethod(sMemberMethodConst< Type,size_t,void * const,& Type :: Serialize> *);
template< typename Type> static long HasSerializeMethod(...);
template< typename Type> static char HasDeserializeMethod(sMemberMethod< Type,size_t,const void * const,& Type :: Deserialize> *);
template< typename Type> static long HasDeserializeMethod(...);
//其他特定的方法检查...

enum
{
HAS_CUSTOM_SIZE_METHOD =(sizeof(HasCustomSizeMethod< T>(0))== sizeof ),
HAS_SERIALIZE_METHOD =(sizeof(HasSerializeMethod< T>(0))== sizeof(char)),
HAS_DESERIALIZE_METHOD =(sizeof(HasDeserializeMethod< T>(0) ),
IS_CUSTOM = HAS_CUSTOM_SIZE_METHOD&&
HAS_SERIALIZE_METHOD&&&
HAS_DESERIALIZE_METHOD,
//其他'快捷键'...
};

我在GCC编译时得到的错误是:



声明模板中的无效参数类型'void'< class Type,class Return,class Parameter,Return(Type :: * Pointer)(Parameter)const> struct sMemberMethodChecker 的第一行中的$ c>



。我相信我不会失踪 typename s也不会错位的话,但我不明白为什么我得到错误,不理解错误。



我知道MSVC很宽松,标准,而GCC很好地符合标准,所以我想知道是否问题是在MSVC侧,允许愚蠢的代码



以下是问题:




    <为什么我在 struct sMemberMethodChecker ?中获得无效参数类型void错误。
  • 为什么代码在MSVC中有效,但在GCC中无效。

  • 此代码是否是非标准的?

  • SFINAE不包括C ++ 11的技巧?


解决方案


我在struct
sMemberMethodChecker中获取无效的参数类型void错误。



为什么代码在MSVC中有效,但它不在GCC?。


我相信MSVC是有帮助的,但GCC在这个特定的代码是严格的。因为它不知何故不允许 Return(Type :: *)(void)


这段代码是否是标准的?


直到它不能编译才能说出来。


SFINAE的技巧是不是C ++ 11?


不是。 SFINAE存在于C ++ 11之前。

这是您想要执行的简化方式:

  template< typename ClassName,typename ClassMethodType> 
struct HasMethod
{
template< typename Type,Type Object> struct包含;
typedef char(& yes)[2];

template< typename Class,typename MethodType>
static yes检查(包含< MethodType,& Class :: size> *);
template< typename Class,typename MethodType>
static char检查(...);

static const bool value =(sizeof(Check< ClassName,ClassMethodType>(0))== sizeof(char));
};

HasMethod< ClassName,ClassMethodType> :: value 如果某个类型的成员方法存在于它内部,它就会给你答案。

现在 HasMethod<> >方法命名 size 。但您可以为上述代码创建一个宏,并使函数名称可配置



这是一个使用g ++的工作演示。 p>

I'm working with some SFINAE features; currently in a portion of an application that must run in Linux and Windows; the compiler choices are MSVC (Visual Studio 2010 10.0) for Windows applications and GCC 4.4.5 for the Linux ones.

I must check if some given object provides some functions to perform a custom serialization and call this functions, or do a simple memcpy and sizeof(Object) while the custom serialization methods are not provided.

The problem is that a piece of code compile without warnings nor errors in MSVC but while compiling with GCC, the code is the following:

template
    <
        typename Type,
        typename Return,
        typename Parameter,
        Return (Type::*Pointer)(Parameter) const
    > struct sMemberMethodConst { };

template
    <
        typename Type,
        typename Return,
        typename Parameter,
        Return (Type::*)(Parameter)
    > struct sMemberMethod { };

template<typename T> struct sMemberMethodChecker
{
    template <typename Type> static char HasCustomSizeMethod(sMemberMethodConst<Type, size_t, void, &Type::Size> *);
    template <typename Type> static long HasCustomSizeMethod(...);
    template <typename Type> static char HasSerializeMethod(sMemberMethodConst<Type, size_t, void * const, &Type::Serialize> *);
    template <typename Type> static long HasSerializeMethod(...);
    template <typename Type> static char HasDeserializeMethod(sMemberMethod<Type, size_t, const void * const, &Type::Deserialize> *);
    template <typename Type> static long HasDeserializeMethod(...);
    // Other specific method checks...

    enum
    {
        HAS_CUSTOM_SIZE_METHOD =    (sizeof(HasCustomSizeMethod<T>(0)) == sizeof(char)),
        HAS_SERIALIZE_METHOD =      (sizeof(HasSerializeMethod<T>(0)) == sizeof(char)),
        HAS_DESERIALIZE_METHOD =    (sizeof(HasDeserializeMethod<T>(0)) == sizeof(char)),
        IS_CUSTOM =                 HAS_CUSTOM_SIZE_METHOD &&
                                    HAS_SERIALIZE_METHOD &&
                                    HAS_DESERIALIZE_METHOD,
        // Other 'shortcuts'...
    };

And the error that I'm getting while compiling with GCC is:

invalid parameter type 'void' in declaration template<class Type, class Return, class Parameter, Return (Type::* Pointer)(Parameter)const>

in the first line of the struct sMemberMethodChecker. I'm quite sure that I'm don't missing typenames nor misplacing words but I don't understand why I'm getting the error and doesn't understand the error.

I know that the MSVC is lax with standard while GCC conforms the standard pretty well so I'm wondering if the problem lies into the MSVC side that allows silly code!

Here are the questions:

  • Why am I getting the invalid parameter type 'void' error in the struct sMemberMethodChecker?.
  • Why the code is valid in MSVC but invalid in GCC?.
  • Is this code non-standard?.
  • Is the SFINAE trickery exclusive of C++11?

解决方案

Why I'm getting the invalid parameter type 'void' error in the struct sMemberMethodChecker?.

Why the code is valid in MSVC but it isn't in GCC?.

I believe that MSVC is being helpful however GCC is being stringent in this particular code. As it's somehow not allowing Return (Type::*)(void). However one need to dig it more to know the exact reason.

Is this code no-standard?.

Can't say until it doesn't compile. And searching standard for the features like SFINAE is not everyone's cup of tea.

Is the SFINAE trickery exclusive of C++11?

Not at all. SFINAE existed before C++11.
Here is the simplified way of what you want to do:

template<typename ClassName, typename ClassMethodType>
struct HasMethod
{
  template<typename Type, Type Object> struct Contains;
  typedef char (&yes)[2];

  template<typename Class, typename MethodType>
  static yes Check (Contains<MethodType, &Class::size>*);
  template<typename Class, typename MethodType>
  static char Check (...);

  static const bool value = (sizeof(Check<ClassName,ClassMethodType>(0)) == sizeof(char));
};

HasMethod<ClassName, ClassMethodType>::value gives you the answer if a certain type member method exists inside it or not.
As of now HasMethod<> is exclusive to the method naming size with user provided type. But you can create a macro for above code and make the function name configurable.

Here is a working demo with g++.

这篇关于如何查找特定原型的方法是否存在于类中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆