C 风格转换参考
C-style casting references
考虑以下因素:
template<class T>
struct call_fn;
template< >
struct call_fn< void( ) >
{
using sig = void ( );
void * fn;
void call() &&
{
static_cast< sig * >( fn )( );
}
auto && change()
{
return (call_fn<void __vectorcall( )>&&)(*this);
}
};
template< >
struct call_fn< void __vectorcall( ) >
{
using sig = void __vectorcall( );
void * fn;
void call() &&
{
static_cast< sig * >( fn )( );
}
auto && change()
{
return (call_fn<void ( )>&&)(*this);
}
};
void __vectorcall fast()
{}
void stdd()
{}
void foo()
{
void * f = fast;
void * st = stdd;
call_fn<decltype(stdd)> { f }.change().call();
call_fn<decltype(fast)> { st }.change().call();
}
或者更简单地说,如果您对具体示例不感兴趣:
template<class T>
struct s
{
using t = T;
char f;
};
void foo()
{
auto y = (s<int>&&)(s<float>());
}
在这种情况下,除了元编程之外,对象是相同的,这是一个定义明确的 C 风格转换吗? (因为使用 C++ 转换无法通过任何其他方式完成)
(since it cannot be done any other way using c++ casting)
(s<int>&&)(s<float>());
此转换可以使用 C++ 样式转换完成。等价于:
reinterpret_cast<s<int>&&>(s<float>());
is this a well defined cast
重新解释对另一个的转换引用定义明确。
在这种情况下,通过重新解释的引用进行访问的定义不明确。 s<int>
是不同于 s<float>
的类型,并且该地址没有 s<int>
对象。
请注意,这是异常允许联合类型双关的情况(标准布局结构的公共初始序列):
union U {
s<float> sf;
s<int> si;
};
U u;
u.sf = {};
return u.si.f; // well defined
标准参考:
[class.mem]
The common initial sequence of two standard-layout struct ([class.prop]) types is the longest sequence of non-static data members and bit-fields in declaration order, starting with the first such entity in each of the structs, such that corresponding entities have layout-compatible types, either both entities are declared with the no_unique_address attribute ([dcl.attr.nouniqueaddr]) or neither is, and either both entities are bit-fields with the same width or neither is a bit-field.
In a standard-layout union with an active member of struct type T1, it is permitted to read a non-static data member m of another union member of struct type T2 provided m is part of the common initial sequence of T1 and T2; the behavior is as if the corresponding member of T1 were nominated.
请注意,也允许重新解释第一个成员的地址:
s<float> sf{};
return *reinterpret_cast<char*>(&sf); // well defined
标准参考:
[expr.reinterpret.cast]
An object pointer can be explicitly converted to an object pointer of a different type.
When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is static_cast<cv T*>(static_cast<cv void*>(v))
.
[expr.static.cast]
A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. ... if the original pointer value points to an object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible with a, the result is a pointer to b.
[basic.compound]
Two objects a and b are pointer-interconvertible if:
...
one is a standard-layout class object and the other is the first non-static data member of that object, ...
...
考虑以下因素:
template<class T>
struct call_fn;
template< >
struct call_fn< void( ) >
{
using sig = void ( );
void * fn;
void call() &&
{
static_cast< sig * >( fn )( );
}
auto && change()
{
return (call_fn<void __vectorcall( )>&&)(*this);
}
};
template< >
struct call_fn< void __vectorcall( ) >
{
using sig = void __vectorcall( );
void * fn;
void call() &&
{
static_cast< sig * >( fn )( );
}
auto && change()
{
return (call_fn<void ( )>&&)(*this);
}
};
void __vectorcall fast()
{}
void stdd()
{}
void foo()
{
void * f = fast;
void * st = stdd;
call_fn<decltype(stdd)> { f }.change().call();
call_fn<decltype(fast)> { st }.change().call();
}
或者更简单地说,如果您对具体示例不感兴趣:
template<class T>
struct s
{
using t = T;
char f;
};
void foo()
{
auto y = (s<int>&&)(s<float>());
}
在这种情况下,除了元编程之外,对象是相同的,这是一个定义明确的 C 风格转换吗? (因为使用 C++ 转换无法通过任何其他方式完成)
(since it cannot be done any other way using c++ casting)
(s<int>&&)(s<float>());
此转换可以使用 C++ 样式转换完成。等价于:
reinterpret_cast<s<int>&&>(s<float>());
is this a well defined cast
重新解释对另一个的转换引用定义明确。
在这种情况下,通过重新解释的引用进行访问的定义不明确。 s<int>
是不同于 s<float>
的类型,并且该地址没有 s<int>
对象。
请注意,这是异常允许联合类型双关的情况(标准布局结构的公共初始序列):
union U {
s<float> sf;
s<int> si;
};
U u;
u.sf = {};
return u.si.f; // well defined
标准参考:
[class.mem]
The common initial sequence of two standard-layout struct ([class.prop]) types is the longest sequence of non-static data members and bit-fields in declaration order, starting with the first such entity in each of the structs, such that corresponding entities have layout-compatible types, either both entities are declared with the no_unique_address attribute ([dcl.attr.nouniqueaddr]) or neither is, and either both entities are bit-fields with the same width or neither is a bit-field.
In a standard-layout union with an active member of struct type T1, it is permitted to read a non-static data member m of another union member of struct type T2 provided m is part of the common initial sequence of T1 and T2; the behavior is as if the corresponding member of T1 were nominated.
请注意,也允许重新解释第一个成员的地址:
s<float> sf{};
return *reinterpret_cast<char*>(&sf); // well defined
标准参考:
[expr.reinterpret.cast]
An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is
static_cast<cv T*>(static_cast<cv void*>(v))
.[expr.static.cast]
A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. ... if the original pointer value points to an object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible with a, the result is a pointer to b.
[basic.compound]
Two objects a and b are pointer-interconvertible if:
...
one is a standard-layout class object and the other is the first non-static data member of that object, ...
...