[英]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_ptr
或shared_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.