左值和右值上的 C++ std::is_integral 显示不同的结果

Posted

技术标签:

【中文标题】左值和右值上的 C++ std::is_integral 显示不同的结果【英文标题】:C++ std::is_integral on lvalue and rvalue shows different results 【发布时间】:2020-04-25 09:49:04 【问题描述】:

我创建了一个类型验证器来检查给定参数是否为数字。

template<typename T>
struct is_numeric
    : std::integral_constant<
        bool,
        std::is_integral_v<T> || std::is_floating_point_v<T>
    > ;

template<typename T>
inline constexpr bool is_numeric_v = is_numeric<T>::value;

template<typename T>
constexpr bool is_numeric_tuple(T&& value)
 return is_numeric_v<T>; 

// variadic template implementation is omitted

现在的问题是

int i = 3;
is_numeric_tuple(3)  // returns true
is_numeric_tuple(i)  // returns false

如果我将std::remove_reference 应用到is_numeric_tuple,两个结果都是正确的。

这是否意味着type_traits 的STL 实现如is_integralis_floating_point 等强制给定类型为右值?

如果是这样,为什么?

更新

正如 geza 所指出的,我使用的type_traits 库只指定了一个类型本身,这意味着

std::is_integral_v<int>;    // returns true
std::is_integral_v<int&>;   // returns false
std::is_integral_v<int&&>;  // returns false

问题不在于左值或右值。

【问题讨论】:

【参考方案1】:

您似乎混淆了值类别和类型。它们之间有很强的联系,但并不相同。

type_traits 需要一个 type 参数。在这里讨论右值是没有意义的,因为表达式有值类别。

is_integral 需要非引用类型才能返回 trueis_integral_v&lt;int &amp;&amp;&gt;(右值引用)仍然返回false,因为它是一个引用类型。

在您的第一个示例(文字 3)中,T 将被推导出为 intis_numeric_tuple 也将返回 true(因为它是非引用类型)。

在您的第二个示例中,T 将被推断为 int &amp;,因此它将返回 false(因为它是一个引用类型)。

【讨论】:

【参考方案2】:

这些类型特征用于表示不同的类别。每种类型都属于these categories:

int&amp; 类型是引用类型,而不是整数类型。因此,is_integral 返回false

【讨论】:

以上是关于左值和右值上的 C++ std::is_integral 显示不同的结果的主要内容,如果未能解决你的问题,请参考以下文章

C++ 函数透明地采用左值和右值参数

C++:神一样的左值

c++中的左值和右值,右值引用到底是啥?关于引用这一节看得很迷糊。

后缀(前缀)增量、左值和右值(在 C 和 C++ 中)

左值和右值

C++内功修炼干货,进大厂必须会的C++左值与右值,最适合小白看的文章!