首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SFINAE方法比较

SFINAE方法比较
EN

Stack Overflow用户
提问于 2010-12-05 19:35:21
回答 3查看 728关注 0票数 6

下面的代码显示了在编译时检查一个类型(基本上是一个类)是否包含成员函数member_func的SFINAE实现。

代码语言:javascript
复制
#define CHECKER(func_name,class_name) sizeof(class_name<T>::template func_name<T>(0)) == 1
#include <iostream>
struct A
{
    void member_func();
};
struct B {};
template<typename T>struct Check_If_T_Is_Class_Type
{
    template<typename C> static char func (char C::*p);
    template<typename C> static long func (...);
    enum{val = CHECKER(func,Check_If_T_Is_Class_Type)};
};

//APPROACH 1
template <typename T>struct TypeHasMemberFunc
{
    template <typename C, C> struct TypeCheck;
    template <typename C> struct Prototype_Holder {typedef void (C::*fptr)();};
    template <typename C> static char func(TypeCheck
                                           <
                                              typename Prototype_Holder<C>::fptr,
                                              &C::member_func
                                           >*);
    template <typename C> static long func(...);
    enum {value = CHECKER(func,TypeHasMemberFunc)};
};

//APPROACH 2
template <typename T>struct has_member_func
{
    template<class C> static char func(char (*)[sizeof(&C::member_func)]);
    template<class C> static long func(...);
    enum{value = CHECKER(func,has_member_func)};
};
int main(){
 if(Check_If_T_Is_Class_Type<A>::val)
   std::cout<<TypeHasMemberFunc<A>::value; //using APPROACH 1

 if(Check_If_T_Is_Class_Type<B>::val)
   std::cout<<has_member_func<B>::value; //using APPROACH 2
}

然而,我的问题是,您更喜欢哪种方法(方法1或方法2)?为什么?

在给定的方法中,您是否发现有任何不一致之处?如果是,请告诉我。

附言:假设sizeof(char)!= sizeof(long)

EN

回答 3

Stack Overflow用户

发布于 2010-12-06 00:40:34

第二种方法不检查函数类型(返回类型或参数类型),并且适用于所有类型,而不仅仅是类类型。

票数 1
EN

Stack Overflow用户

发布于 2010-12-06 03:01:23

我个人更喜欢第二种方法,因为它更简短,更容易理解。但是GCC不会编译它,所以你必须对GCC使用类似的东西:

代码语言:javascript
复制
namespace detail
{
    template<class C> char func(char (*)[sizeof(&C::member_func)]);
    template<class C> long func(...);   
}

template <typename T>struct has_member_func
{
    enum{value = (sizeof(detail::func<T>(0)) == 1)};
};

另外,如果能摆脱CHECKER宏,那就更好了。这会使你的代码可读性极差。

无论如何,我会避免在产品代码中使用这样的C++ hack(除非您是Boost团队成员:-)

这样的东西容易出错,很难支持,几乎不能在编译器之间移植,但主要的一点是,我不记得有任何现实生活中的任务需要这样的硬编码C++。

票数 0
EN

Stack Overflow用户

发布于 2010-12-05 19:46:15

编辑:已完成,已更正。

另一种方法,使用继承的二义性,可能在功能上等同于你的方法2。我记得方法1有问题(尽管它是用G++ 4.4.5编译的),因为名称解析触发了一个错误,而不是替换失败。我不得不求助于:

代码语言:javascript
复制
template <class T>
struct has_foo
{
  struct fallback { void foo(...); };
  struct D : T, fallback { };

  template <typename U, U> struct K;

  // Will be ambiguous for U = D iff T has a foo member function.                                                                                                         
  // It doesn't trigger an error, since D will always have at least one                                                                                                   
  // foo member function.                                                                                                                                                 
  template <class U> static char (&test(K<void (fallback::*)(...), &U::foo>*))[1];
  template <class U> static char (&test(...))[2];

  static const bool value = sizeof(test<D>(0)) == 2;
};

当T是一个类时,这是有效的,所以你可能想要添加你的层来检查T是否是一个类类型。

注意,任何foo成员函数都将被检测到。如果你想检查检测到的foo函数是否可以用给定的参数调用,你必须做另一层SFINAE:

代码语言:javascript
复制
// Check whether foo can be called with an argument of type Arg
// and yields an element of type Res.
// If you need Res = void, this code does not work.
template <class T, typename Arg, typename Res>
struct check_foo
{
    struct flag {};
    struct D : T { using T::foo; flag foo(...); };

    template <typename U>
    static char (&test(U))[1];

    template <typename> static char (&test(...))[2];

    static Arg f();

    static const bool value = sizeof(test<Arg>( ((D*)0)->foo(f()) )) == 1;
};
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4358584

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档