检查成员存在,可能在基类C ++ 11中 [英] Checking a member exists, possibly in a base class, C++11 version

查看:146
本文介绍了检查成员存在,可能在基类C ++ 11中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

http://stackoverflow.com/a/1967183/134841 中,提供了一种解决方案,用于静态检查成员存在,可能在类型的子类中:

  template< typename Type> 
class has_resize_method
{
class yes {char m;};
class no {yes m [2];};
struct BaseMixin
{
void resize(int){}
};
struct Base:public Type,public BaseMixin {};
template< typename T,T t> class Helper {};
template< typename U>
static no deduce(U *,Helper< void(BaseMixin :: *)(),& U :: foo> * = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes)== sizeof(deduce((Base *)(0)));
};

但是,它不适用于C ++ 11 final 类,因为它从测试类继承, final 阻止。



<这一个:

 模板< typename C> 
struct has_reserve_method {
private:
struct No {};
struct Yes {No no [2]; };
template< typename T,typename I,void(T :: *)(I)> struct sfinae {};
template< typename T>静态无检查(...);
template< typename T> static是检查(sfinae< T,int,& T :: reserve> *);
template< typename T> static是检查(sfinae< T,size_t,& T :: reserve> *);
public:
static const bool value = sizeof(check< C>(0))== sizeof(Yes);
};

无法找到 reserve(int / size_t)

这个元函数的实现在基类中找到 reserved() T 并且仍然有效,如果 T final p>

解决方案

实际上,在C ++ 11中,由于 decltype 和延迟返回绑定机制。



现在,使用方法测试这个更简单:

  //如果保留不存在或不可访问,则由SFINAE舍弃
template< typename T>
constexpr auto has_reserve_method(T& t) - > decltype(t.reserve(0),bool()){
return true;
}

//当SFINAE舍弃模板方法时用作回退
constexpr bool has_reserve_method(...){return false; }

然后,您可以在类中使用这个例子:

  template< typename T,bool b> 
struct Reserver {
static void apply(T& t,size_t n){t.reserve(n); }
};

template< typename T>
struct Reserver< T,false> {
static void apply(T& t,size_t n){}
};

您使用它:

  template< typename T> 
bool reserve(T& t,size_t n){
Reserver< T,has_reserve_method(t)> :: apply(t,n);
return has_reserve_method(t);
}

或者您可以选择 enable_if 方法:

  template< typename T> 
自动预留(T& t,size_t n) - > typename std :: enable_if< has_reserve_method(t),bool> :: type {
t.reserve(n);
return true;
}

template< typename T>
自动预留(T& t,size_t n) - > typename std :: enable_if< not have_reserve_method(t),bool> :: type {
return false;
}

请注意,这种切换事实上并不那么容易。一般来说,只要SFINAE存在就容易多了 - 你只需要 enable_if 一个方法,而不提供任何回退:

  template< typename T> 
自动预留(T& t,size_t n) - > decltype(t.reserve(n),void()){
t.reserve(n);
}

如果替换失败,则从可能的重载列表中删除此方法。 / p>

注意:由于(逗号运算符)的语义, code> decltype ,只有最后一个实际决定了类型。方便检查多个操作。


In http://stackoverflow.com/a/1967183/134841, a solution is provided for statically checking whether a member exists, possibly in a subclass of a type:

template <typename Type> 
class has_resize_method
{ 
   class yes { char m;}; 
   class no { yes m[2];}; 
   struct BaseMixin 
   { 
     void resize(int){} 
   }; 
   struct Base : public Type, public BaseMixin {}; 
   template <typename T, T t>  class Helper{}; 
   template <typename U> 
   static no deduce(U*, Helper<void (BaseMixin::*)(), &U::foo>* = 0); 
   static yes deduce(...); 
public: 
   static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0))); 
};

However, it doesn't work on C++11 final classes, because it inherits from the class under test, which final prevents.

OTOH, this one:

template <typename C>
struct has_reserve_method {
private:
    struct No {};
    struct Yes { No no[2]; };
    template <typename T, typename I, void(T::*)(I) > struct sfinae {};
    template <typename T> static No  check( ... );
    template <typename T> static Yes check( sfinae<T,int,   &T::reserve> * );
    template <typename T> static Yes check( sfinae<T,size_t,&T::reserve> * );
public:
    static const bool value = sizeof( check<C>(0) ) == sizeof( Yes ) ;
};

fails to find the reserve(int/size_t) method in baseclasses.

Is there an implementation of this metafunction that both finds reserved() in baseclasses of T and still works if T is final?

解决方案

Actually, things got much easier in C++11 thanks to the decltype and late return bindings machinery.

Now, it's just simpler to use methods to test this:

// Culled by SFINAE if reserve does not exist or is not accessible
template <typename T>
constexpr auto has_reserve_method(T& t) -> decltype(t.reserve(0), bool()) {
  return true;
}

// Used as fallback when SFINAE culls the template method
constexpr bool has_reserve_method(...) { return false; }

You can then use this in a class for example:

template <typename T, bool b>
struct Reserver {
  static void apply(T& t, size_t n) { t.reserve(n); }
};

template <typename T>
struct Reserver <T, false> {
  static void apply(T& t, size_t n) {}
};

And you use it so:

template <typename T>
bool reserve(T& t, size_t n) {
  Reserver<T, has_reserve_method(t)>::apply(t, n);
  return has_reserve_method(t);
}

Or you can choose a enable_if method:

template <typename T>
auto reserve(T& t, size_t n) -> typename std::enable_if<has_reserve_method(t), bool>::type {
  t.reserve(n);
  return true;
}

template <typename T>
auto reserve(T& t, size_t n) -> typename std::enable_if<not has_reserve_method(t), bool>::type {
  return false;
}

Note that this switching things is actually not so easy. In general, it's much easier when just SFINAE exist -- and you just want to enable_if one method and not provide any fallback:

template <typename T>
auto reserve(T& t, size_t n) -> decltype(t.reserve(n), void()) {
  t.reserve(n);
}

If substitution fails, this method is removed from the list of possible overloads.

Note: thanks to the semantics of , (the comma operator) you can chain multiple expressions in decltype and only the last actually decides the type. Handy to check multiple operations.

这篇关于检查成员存在,可能在基类C ++ 11中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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