static_assertupcast是否需要调整指针
static_assert whether pointer adjustment is required for an upcast
我想执行编译时检查,以确定从派生类型到基类型的向上转换是否需要指针调整。我从 type_traits
中看不到任何可以使用的东西。这能做到吗?
这是一个如何在运行时完成此操作的示例。请注意,clang 甚至会警告第一个 printf
永远不会打印“yes”,第二个永远不会打印“no”,因此它会将这些调整值评估为常量。问题是,如何在编译时访问这些值?
#include <stdio.h>
struct A
{
int a;
};
struct B
{
int b;
};
struct C: A, B
{
int c;
};
int main()
{
C c;
// Prints "no"
printf( "Is pointer adjustment required when casting from C to A? %s\n",
( ( char * ) ( A * ) &c - ( char * ) &c ) ? "yes" : "no" );
// Prints "yes"
printf( "Is pointer adjustment required when casting from C to B? %s\n",
( ( char * ) ( B * ) &c - ( char * ) &c ) ? "yes" : "no" );
// Can we have those values as constexpr though?
return 0;
}
这称为指针互换性。有一个特质std::is_pointer_interconvertible_base_of
which unfortunately isn't implemented yet in gcc and clang. See also the paper and issue。指针可互换类型具有相同的地址,它们的指针可以在 reinterpret_cast
.
之间转换
#include <type_traits>
#ifdef __cpp_lib_is_pointer_interconvertible
// Prints "no"
printf( "Is pointer adjustment required when casting from C to A? %s\n",
std::is_pointer_interconvertible_base_of_v<A, C> ? "no" : "yes" );
// Prints "yes"
printf( "Is pointer adjustment required when casting from C to B? %s\n",
std::is_pointer_interconvertible_base_of_v<B, C> ? "no" : "yes" );
#endif
这是一个不需要 C++20 的可能实现:
template< class Base, class Derived >
struct is_pointer_interconvertible_base_of
{
private:
// Note that this doesn't seem to be ODR-used in the end, so an actual
// instance isn't needed. Clang generates a warning about needing to
// instantiate it, but linking succeeds nevertheless
static Derived derived;
public:
// Suppress that clang warning :)
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundefined-var-template"
#endif
// TODO: add std::is_base_of check etc
static constexpr bool value = ( ( void const * ) &derived ==
( Base const * ) &derived );
#ifdef __clang__
#pragma clang diagnostic pop
#endif
};
struct A
{
int a;
};
struct B
{
int b;
};
struct C: A, B
{
int c;
};
static_assert( is_pointer_interconvertible_base_of< A, C >::value,
"pointer adjustment isn't expected when casting from C to A" );
static_assert( !is_pointer_interconvertible_base_of< B, C >::value,
"pointer adjustment is expected when casting from C to B" );
int main()
{
return 0;
}
似乎适用于 clang 和 gcc。 Clang 生成了需要实例化derived
的警告,但最后好像不是这样。这里没有处理 Derived
实际上不是从 Base
派生的情况,但是很容易添加 std::is_base_of
检查和其他需要的检查。不知道这是否符合标准,但在更广泛地提供 C++20 支持之前它可能会有所帮助。
我想执行编译时检查,以确定从派生类型到基类型的向上转换是否需要指针调整。我从 type_traits
中看不到任何可以使用的东西。这能做到吗?
这是一个如何在运行时完成此操作的示例。请注意,clang 甚至会警告第一个 printf
永远不会打印“yes”,第二个永远不会打印“no”,因此它会将这些调整值评估为常量。问题是,如何在编译时访问这些值?
#include <stdio.h>
struct A
{
int a;
};
struct B
{
int b;
};
struct C: A, B
{
int c;
};
int main()
{
C c;
// Prints "no"
printf( "Is pointer adjustment required when casting from C to A? %s\n",
( ( char * ) ( A * ) &c - ( char * ) &c ) ? "yes" : "no" );
// Prints "yes"
printf( "Is pointer adjustment required when casting from C to B? %s\n",
( ( char * ) ( B * ) &c - ( char * ) &c ) ? "yes" : "no" );
// Can we have those values as constexpr though?
return 0;
}
这称为指针互换性。有一个特质std::is_pointer_interconvertible_base_of
which unfortunately isn't implemented yet in gcc and clang. See also the paper and issue。指针可互换类型具有相同的地址,它们的指针可以在 reinterpret_cast
.
#include <type_traits>
#ifdef __cpp_lib_is_pointer_interconvertible
// Prints "no"
printf( "Is pointer adjustment required when casting from C to A? %s\n",
std::is_pointer_interconvertible_base_of_v<A, C> ? "no" : "yes" );
// Prints "yes"
printf( "Is pointer adjustment required when casting from C to B? %s\n",
std::is_pointer_interconvertible_base_of_v<B, C> ? "no" : "yes" );
#endif
这是一个不需要 C++20 的可能实现:
template< class Base, class Derived >
struct is_pointer_interconvertible_base_of
{
private:
// Note that this doesn't seem to be ODR-used in the end, so an actual
// instance isn't needed. Clang generates a warning about needing to
// instantiate it, but linking succeeds nevertheless
static Derived derived;
public:
// Suppress that clang warning :)
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundefined-var-template"
#endif
// TODO: add std::is_base_of check etc
static constexpr bool value = ( ( void const * ) &derived ==
( Base const * ) &derived );
#ifdef __clang__
#pragma clang diagnostic pop
#endif
};
struct A
{
int a;
};
struct B
{
int b;
};
struct C: A, B
{
int c;
};
static_assert( is_pointer_interconvertible_base_of< A, C >::value,
"pointer adjustment isn't expected when casting from C to A" );
static_assert( !is_pointer_interconvertible_base_of< B, C >::value,
"pointer adjustment is expected when casting from C to B" );
int main()
{
return 0;
}
似乎适用于 clang 和 gcc。 Clang 生成了需要实例化derived
的警告,但最后好像不是这样。这里没有处理 Derived
实际上不是从 Base
派生的情况,但是很容易添加 std::is_base_of
检查和其他需要的检查。不知道这是否符合标准,但在更广泛地提供 C++20 支持之前它可能会有所帮助。