私有const成员函数的成员检测

时间:2019-07-12 09:40:06

标签: c++

当成员为const和私有成员时,我正在尝试为成员检测器构建特征。我可以使用 wikibook中的成语DetectX

template<typename T>
class DetectX
{
    struct Fallback { int X; }; // add member name "X"
    struct Derived : T, Fallback { };

    template<typename U, U> struct Check;

    typedef char ArrayOfOne[1];  // typedef for an array of size one.
    typedef char ArrayOfTwo[2];  // typedef for an array of size two.

    template<typename U> 
    static ArrayOfOne & func(Check<int Fallback::*, &U::X> *);

    template<typename U> 
    static ArrayOfTwo & func(...);

  public:
    typedef DetectX type;
    enum { value = sizeof(func<Derived>(0)) == 2 };
};

但是这个习惯用法并没有在私有const成员函数和私有非const成员函数之间进行区分,只是碰巧同时检测到non-constconst private成员函数。

我认为当您取const的地址时,(&U::X)信息就会丢失。

我如何检测私有成员函数并区分同一类的const和非const私有成员函数?

查看Tyker的代码后,我可以使用friend获得C ++ 03实现。我还在等没有朋友的情况下解决问题。

/* Start - decltype simulation in c++03 */
template <size_t>
struct TypeId;

#define REGISTER_TYPE(T, id)               \
  template <>                              \
  struct TypeId<id> {                      \
    char value[id];                        \
    typedef T type;                        \
    static char const* const name;         \
  };                                       \
  char const* const TypeId<id>::name = #T; \
  TypeId<id> type_to_id(T);

#define TYPEID_(value) TypeId<sizeof(type_to_id(value))>
#define TYPEOF(value) typename TYPEID_(value)::type
#define TYPENAME(value) TYPEID_(value)::name

REGISTER_TYPE(int, 1)
REGISTER_TYPE(unsigned int, 2)

/* End - decltype simulation - c++03 */

template <typename T>
class DetectX {
  template <typename V>
  struct Check;

  template <typename U>
  static char& func(
      Check<TYPEOF((*(const U*)0).mem())>*);  // use const U* or U*

  template <typename U>
  static short& func(...);

 public:
  typedef DetectX type;
  enum { value = sizeof(func<T>(0)) };  // returns 1 or 2
};

class bar {
 private:
  int mem() const;
  template <typename T>
  friend class DetectX;
};
/* Register class  and function signatures */

#define REGISTER_CLASS(X) \
  typedef int (X::*pf)(); \
  typedef int (X::*pfc)() const;

REGISTER_CLASS(bar)
REGISTER_TYPE(pf, 3)
REGISTER_TYPE(pfc, 4)

int main() { std::cout << DetectX<bar>::value << std::endl; }

2 个答案:

答案 0 :(得分:0)

std::declval<T>()生成对象,然后将其强制转换为const,然后调用成员函数。在SFINAE函数中执行此操作。该函数应具有两个具有不同返回类型的重载版本。使用decltypestd::is_same检查返回类型,以了解成员函数是否为const限定。

答案 1 :(得分:0)

可以使用以下代码检测const私有成员。

唯一的缺点是朋友声明,但我认为没有它就无法做到。

template<typename T, typename...>
using first_type = T;

class private_const_test {
    template<typename = void>
    static constexpr std::false_type has_const_test_impl(...) {
        return std::false_type();
    }

    template<typename T>
    static constexpr first_type<std::true_type, decltype(std::declval<const T>().test())> has_const_test_impl(T) {
        return std::true_type();
    }
public:
    template<typename T>
    static constexpr bool has_const_test = decltype(has_const_test_impl(std::declval<T>()))::value;
};

class public_const_test {
    template<typename = void>
    static constexpr std::false_type has_const_test_impl(...) {
        return std::false_type();
    }

    template<typename T>
    static constexpr first_type<std::true_type, decltype(std::declval<const T>().test())> has_const_test_impl(T) {
        return std::true_type();
    }
public:
    template<typename T>
    static constexpr bool has_const_test = decltype(has_const_test_impl(std::declval<T>()))::value;
};

template<typename T>
constexpr bool has_private_const_test = private_const_test::has_const_test<T> && !public_const_test::has_const_test<T>;

struct A {
    friend class private_const_test;
  private:
    void test() const {}
};

struct B {
    friend class private_const_test;
    void test() const {}
};

int main()
{
    std::cout << has_private_const_test<A> << std::endl; // true
    std::cout << has_private_const_test<B> << std::endl; // false
    std::cout << has_private_const_test<int> << std::endl; // false
}