简体   繁体   English

C ++严格别名规则和指向成员的指针

[英]C++ strict aliasing rules and pointers to members

The following code yields warning in G++: 以下代码在G ++中产生警告:

#include <iostream>
#include <cstdint>

template <typename T, typename P, typename Q>
Q T::*pointer_to(P T::*p, Q P::*q)
{
   typedef Q T::* output_ptr;
// warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
   size_t tmp = reinterpret_cast<const size_t&>(p) + reinterpret_cast<const size_t&>(q);
   return reinterpret_cast<const output_ptr&>(tmp);
}

struct A { int x; };
struct B { A a; };

int main()
{
   B b = B();
   b.*pointer_to(&B::a, &A::x) = 1;
   std::cout << b.a.x << std::endl;
}

It works properly anyway, but that makes me worry. 无论如何它都能正常工作,但这让我很担心。

What is your opinion, are these "sub-member" pointers susceptible to extra strict aliasing issues than plain member pointers? 您有什么看法,这些“子成员”指针是否容易受到比普通成员指针更严格的别名问题的影响?

I would recommend against doing it this way. 我建议不要这样做。

You stated in your comments that you tried using a nested std::bind , but there's an issue with the compiler version you're using. 您在评论中表示您尝试使用嵌套的std::bind ,但是您使用的编译器版本存在问题。 Rather than resort to the hack, I would roll my own repeated pointer to member class. 我会将自己重复的指针滚动到成员类,而不是诉诸黑客。

#include <iostream>
#include <cstdint>
#include <type_traits>
#include <utility>


template<typename Ptr1, typename... Rest>
class pointer_to_sub;

template<typename ObjType, typename Class>
class pointer_to_sub<ObjType Class::* >
{
  typedef ObjType Class::* ptr_type;

public:
  typedef ObjType value_type;
  typedef Class input_type;
  pointer_to_sub(ptr_type input)  : ptr(input)
  {

  }

  value_type& operator()(input_type& from) const
  {
    return from.*ptr;
  }

  value_type const& operator()(input_type const& from) const
  {
    return from.*ptr;
  }

  value_type& operator()(input_type* from) const
  {
    return from->*ptr;
  }

  value_type const& operator()(input_type const* from) const
  {
    return from->*ptr;
  }



  private:

  ptr_type ptr;
};


template<typename ObjType, typename Class, typename... Rest >
class pointer_to_sub<ObjType Class::*, Rest...> : private pointer_to_sub<Rest...>
{
  typedef ObjType Class::* ptr_type;
  typedef pointer_to_sub<Rest...> base_type;
public:
  typedef typename base_type::value_type value_type;
  typedef Class input_type;

  pointer_to_sub(ptr_type input, Rest... args) : base_type(args...), ptr(input)
  {

  } 

  value_type& operator()(input_type& from) const
  {
    return base_type::operator()(from.*ptr);
  }

  value_type const& operator()(input_type const& from) const
  {
    return base_type::operator()(from.*ptr);
  }


  value_type& operator()(input_type* from) const
  {
    return base_type::operator()(from->*ptr);
  }

  value_type const& operator()(input_type const* from) const
  {
    return base_type::operator()(from->*ptr);
  } 
private:
  ptr_type ptr;
};

template<typename T, typename... Args>
pointer_to_sub<T, Args...> make_pointer_to_sub(T t1, Args... args)
{
  return pointer_to_sub<T, Args...>(t1, args...);
}

The above basically provides a make_pointer_to_sub which takes a list of member object pointers. 以上基本上提供了一个make_pointer_to_sub ,它接受一个成员对象指针列表。 It accepts as its input a reference or a pointer that's convertible to the first type, and then dereferences each of the pointers in turn. 它接受一个可转换为第一种类型的引用或指针作为其输入,然后依次取消引用每个指针。 It could be improved to accept unique_ptr or shared_ptr , but that's for later. 它可以被改进以接受unique_ptrshared_ptr ,但这是为了以后。 You use it as seen below. 你可以使用它,如下所示。

struct A { int x; double y;};
struct B { A a; };

int main()
{
  auto ptr = make_pointer_to_sub(&B::a, &A::x);


   B b = B();
   ptr(b) = 1;
   // b.*pointer_to(&B::a, &A::x) = 1;

   std::cout << b.a.x << std::endl;
   ptr(&b) = 2;
   std::cout << b.a.x << std::endl;

}

If you needed to, this could be assigned to a std::function with the appropriate arguments. 如果需要,可以使用适当的参数将其分配给std::function

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM