5
#include <type_traits>

template<typename T>
void f(const T&)
{
    static_assert(std::is_array_v<T>); // ok
}

template<typename T>
void g(T&&)
{
    static_assert(std::is_array_v<T>); // error
}

int main()
{
    char arr[8];
    f(arr); // ok
    g(arr); // error
}

我的编译器是 clang 7.0 和-std=c++17.

为什么通用引用不适用于数组?

4

2 回答 2

11

首先,这些被官方称为“转发引用”,而不是 “通用引用”

您的失败是因为在将左值传递给采用“转发引用”的函数时推断出static_assert的事实- 这是在模板参数推导期间适用的“转发引用”的特殊规则之一。TT&

您可以通过首先删除任何引用来修复您的断言:

static_assert(std::is_array_v<std::remove_cvref_t<T>>); 

godbolt.org 上的实时示例


std::remove_cvref_t是一个前沿的 C++20 特性——std::remove_reference_t如果你的编译器不支持它,你可能想要使用它。

于 2018-11-08T10:46:18.257 回答
0

这里发生模板参数推导时的相关规则是:

从函数调用中推导
...
4. 如果 P 是对 cv 不合格模板参数的右值引用(所谓的转发引用),并且对应的函数调用参数是左值,则对 A 的类型左值引用用于扣A的地方。

因此,在您的情况下,arr被推断为参考 arr,因此static_assert失败。

于 2018-11-08T11:05:26.100 回答