static_cast <t> vs T(n)表示基本类型

时间:2017-01-19 18:33:16

标签: c++ c++11 constructor primitive static-cast

我们假设我有一个像这样的宏:

#define IS_SIGNED_B(T) (static_cast<T>(-1)<0)

将它写成

是否可以
#define IS_SIGNED_B(T) (T(-1)<0)

知道T是(应该)总是一个基本类型。以及其他各种情况,我需要某个值明确表示某种类型。

我知道这会导致以下情况出现问题:

signed char(0);

但我知道我有基本类型typedef'ed:

typedef signed char Int8;
Int8(0);

除此之外还有其他问题吗?可以认为基本类型的构造函数与静态类型相同吗?

编辑:我知道std::numeric_limitsstd::is_signed的存在。这只是一个例子。不是实际情况。我很抱歉没有提到这一点。

2 个答案:

答案 0 :(得分:4)

  

基本类型的构造函数可以被认为与静态转换相同吗?

基本类型没有构造函数。 Int8(0)(Int8)0的显式类型转换和替代语法。这被称为C风格演员。替代语法称为功能强制转换表达式。

对于基本积分类型,C样式转换等同于static_cast。但它一般不等同。如果没有static_cast可用,那么它将执行reinterpret_cast(或const_cast,或const_cast的组合,以及其他一个强制转换)。

  

除此之外还有其他问题吗?

我不太了解您提出的问题,但明确的类型转换确实存在重大问题。主要问题是程序员并不完美,你不能认为T is (should) always be a fundamental type总是成立。您希望编译器捕获此类错误。 C风格的演员表会隐藏您或您的同事可能犯的一些错误,并用未定义的行为替换错误消息。

也许在宏的上下文中,存在未定义行为的危险,但正如您所说,这只是一个例子。一个好的经验法则:首选使用您想要的确切类型的* _cast,而不是让C风格的角色选择其中一个可能不是您想要的角色。

答案 1 :(得分:2)

你应该做的第一件事是不必要地停止使用C预处理器。

只需使用std::is_signed

失败,例如:

template<class T>
constexpr
std::integral_constant<bool,
  (static_cast<T>(-1)<0)
> is_signed_b() { return {}; }

这是宏的工业强度版本。

它返回一个空类,它有一个constexpr转换为bool,其值是您想要的结果。它可以在编译时进行评估(事实上,它很难不被编译)。

但你的宏有什么问题?

首先,你的宏应该是:

#define IS_SIGNED_B(...) (static_cast<__VA_ARGS__>(-1)<0)

,因为

IS_SIGNED_B( std::tuple_element_t<some_tuple, Is> )...

不必要地执行您的实施。

C预处理器不理解C ++。它不理解,()中不再包含{}

如上所述,如果T是双字类型,则代码会中断。

另一个问题是,如果你提供一个不是整数类型的类型,就会发生奇怪的事情。 C风格的强制转换很强大,适用于指针类型。因此,您将在左侧获得指针类型值-1。在右侧,您将获得0,它隐式转换为任何指针类型的空值。然后比较事情。本段包含各种未定义的行为。