C++ 元编程成员检查器不';t处理返回带有基类的类型的函数成员

C++ 元编程成员检查器不';t处理返回带有基类的类型的函数成员,c++,templates,metaprogramming,C++,Templates,Metaprogramming,我实现了一个元编程成员检查器,如下所示: //Declare a metaprogramming test to check if a class has a member //of a given signature and a certain name #define DECL_hasMember(MEMBER) \ /* Check if T has member MEMBER M is a

我实现了一个元编程成员检查器,如下所示:

//Declare a metaprogramming test to check if a class has a member
//of a given signature and a certain name
#define DECL_hasMember(MEMBER)                                                  \
/* Check if T has member MEMBER M is a pointer to member of T type (T::*) */    \
template <typename T, typename M>                                               \
class hasMember_##MEMBER {                                                      \
    private:                                                                    \
        typedef char passed[1];                                                 \
        typedef char failed[2];                                                 \
                                                                                \
        template <typename U, U> struct reallyHas;                              \
                                                                                \
        template <typename C> static passed& test(reallyHas<M, &C::MEMBER>*);   \
        template <typename C> static failed& test(...);                         \
                                                                                \
        hasMember_##MEMBER()=delete;                                            \
    public:                                                                     \
        static bool const value = sizeof(test<T>(nullptr)) == sizeof(passed);   \
}
如前所述,静态断言失败,即它无法检测
test::buildFSM
。问题出在
desc\t
中,因为如果我将其更改为另一种类型,测试通过得很好。如果我修改了
desc\t
,因此它不会派生
std::map
,测试也会通过。为什么会发生这种情况?在这种情况下,我能做些什么来完成这项工作吗?我知道另一种选择是将map作为成员而不是基类,但我不明白为什么会发生这种情况

我在Visual Studio 2015中。

结帐:

以下是一些用于检测成员函数的代码:

#include <iostream>

// single argument and return type
#define DECL_hasMemberRetArg(MEMBER)                                          \
template<typename T, typename RESULT, typename ARG1>                          \
class Detect_RetArg_##MEMBER                                                  \
{                                                                             \
    template <typename U, RESULT (U::*)(ARG1)> struct Check;                  \
    template <typename U> static char func(Check<U, &U::MEMBER> *);           \
    template <typename U> static int func(...);                               \
  public:                                                                     \
    typedef Detect_RetArg_##MEMBER type;                                      \
    enum { value = sizeof(func<T>(0)) == sizeof(char) };                      \
}

// two arguments and return type
#define DECL_hasMemberRetArgArg(MEMBER)                                       \
template<typename T, typename RESULT, typename ARG1, typename ARG2>           \
class Detect_RetArgArg_##MEMBER                                               \
{                                                                             \
    template <typename U, RESULT (U::*)(ARG1, ARG2)> struct Check;            \
    template <typename U> static char func(Check<U, &U::MEMBER> *);           \
    template <typename U> static int func(...);                               \
  public:                                                                     \
    typedef Detect_RetArgArg_##MEMBER type;                                   \
    enum { value = sizeof(func<T>(0)) == sizeof(char) };                      \
}

class a_t
{
  char get(int);
  char put(int,long);
};

struct b_t
{
  char get(int);
  char put(int,long);
};

struct c_t : public b_t
{
};

DECL_hasMemberRetArg(get);
DECL_hasMemberRetArgArg(put);

int main()
{
  std::cout << Detect_RetArg_get<a_t, char, int>::value << "\n";          // 0
  std::cout << Detect_RetArgArg_put<a_t, char, int, long>::value << "\n"; // 0
  std::cout << Detect_RetArg_get<b_t, char, int>::value << "\n";          // 1
  std::cout << Detect_RetArgArg_put<b_t, char, int, long>::value << "\n"; // 1
  std::cout << Detect_RetArg_get<c_t, char, int>::value << "\n";          // 0
  std::cout << Detect_RetArgArg_put<c_t, char, int, long>::value << "\n"; // 0
  return 0;
}
#包括
//单参数和返回类型
#定义DECL_hasMemberRetArg(成员)\
模板\
类Detect_RetArg_35;##成员\
{                                                                             \
模板结构检查\
模板静态字符函数(检查*)\
模板静态int func(…)\
公众:\
typedef Detect_RetArg_35;#成员类型\
枚举{value=sizeof(func(0))==sizeof(char)}\
}
//两个参数和返回类型
#定义DECL_HasMemberRetarg(成员)\
模板\
类检测重新组织成员\
{                                                                             \
模板结构检查\
模板静态字符函数(检查*)\
模板静态int func(…)\
公众:\
typedef Detect_RetArgArg_35;##成员类型\
枚举{value=sizeof(func(0))==sizeof(char)}\
}
a类
{
字符获取(int);
字符put(int,long);
};
结构b_t
{
字符获取(int);
字符put(int,long);
};
结构c\u t:公共b\u t
{
};
DECL_hasMemberRetArg(get);
DECL_HasmemberRetarg(看跌期权);
int main()
{

std::难道我也在Visual Studio 2015中,这使我的编译器崩溃了吗?我不再感到惊讶了。这并不是用Clang或GCC编译的,这并不奇怪;在实例化
FSM
时,
test
是一个不完整的类型,但是您的
静态\u assert
检查其成员,这当然是失败的。
#include <iostream>

// single argument and return type
#define DECL_hasMemberRetArg(MEMBER)                                          \
template<typename T, typename RESULT, typename ARG1>                          \
class Detect_RetArg_##MEMBER                                                  \
{                                                                             \
    template <typename U, RESULT (U::*)(ARG1)> struct Check;                  \
    template <typename U> static char func(Check<U, &U::MEMBER> *);           \
    template <typename U> static int func(...);                               \
  public:                                                                     \
    typedef Detect_RetArg_##MEMBER type;                                      \
    enum { value = sizeof(func<T>(0)) == sizeof(char) };                      \
}

// two arguments and return type
#define DECL_hasMemberRetArgArg(MEMBER)                                       \
template<typename T, typename RESULT, typename ARG1, typename ARG2>           \
class Detect_RetArgArg_##MEMBER                                               \
{                                                                             \
    template <typename U, RESULT (U::*)(ARG1, ARG2)> struct Check;            \
    template <typename U> static char func(Check<U, &U::MEMBER> *);           \
    template <typename U> static int func(...);                               \
  public:                                                                     \
    typedef Detect_RetArgArg_##MEMBER type;                                   \
    enum { value = sizeof(func<T>(0)) == sizeof(char) };                      \
}

class a_t
{
  char get(int);
  char put(int,long);
};

struct b_t
{
  char get(int);
  char put(int,long);
};

struct c_t : public b_t
{
};

DECL_hasMemberRetArg(get);
DECL_hasMemberRetArgArg(put);

int main()
{
  std::cout << Detect_RetArg_get<a_t, char, int>::value << "\n";          // 0
  std::cout << Detect_RetArgArg_put<a_t, char, int, long>::value << "\n"; // 0
  std::cout << Detect_RetArg_get<b_t, char, int>::value << "\n";          // 1
  std::cout << Detect_RetArgArg_put<b_t, char, int, long>::value << "\n"; // 1
  std::cout << Detect_RetArg_get<c_t, char, int>::value << "\n";          // 0
  std::cout << Detect_RetArgArg_put<c_t, char, int, long>::value << "\n"; // 0
  return 0;
}