【问题标题】:Why is a `std::remove_cv<_Iter>::type` not a type?为什么 `std::remove_cv<_Iter>::type` 不是类型?
【发布时间】:2021-06-16 10:43:01
【问题描述】:

我有两个版本的我希望是相同的功能,但 gcc 说版本 1 是有效的,而版本 2 给出了一个

expected a type, got 'std::remove_cv<_Iter>::type'

我不太明白这个错误,因为我认为 using 语句需要一个类型,并且不会自动将 'std::remove_cv&lt;_Iter&gt;::type' 提升为其他类型?

有人能解释一下这里发生了什么吗?

template<typename U,typename V> constexpr inline auto is_same_rcv() noexcept
{
    //version 1 works
    using u_underlying = std::remove_cv<U>::type;
    using v_underlying = std::remove_cv<V>::type;
    return std::is_same<u_underlying,v_underlying>::value;
}

template<typename U,typename V> constexpr inline auto is_same_rcv() noexcept
{
    //version 2 doesn't work
    using u_underlying = std::remove_cv<U>::type;
    return std::is_same<u_underlying,std::remove_cv<V>::type>::value;
}

关联godbolt

为了好玩而编辑,看起来clang和gcc对using关键字的解释不同(见https://godbolt.org/z/P9Pcn6

【问题讨论】:

  • TL;欺骗的博士,没有typename,语言假定std::remove_cv&lt;U&gt;::type是一个值。
  • @NathanOliver 嗯,这个骗局不是很明显。 typename 会去哪里(它已经在签名中)以及为什么using 可以工作,但当它是模板的一部分时却不行...
  • typename 总是作为名称的前缀,所以using u_underlying = typename std::remove_cv&lt;U&gt;::type;
  • @NathanOliver 或者应该是return std::is_same&lt;u_underlying,typename std::remove_cv&lt;V&gt;::type&gt;::value;
  • 我重新打开了这个问题,因为它似乎关注typenameusing 语句和return 语句中的用法之间的区别。

标签: c++ template-meta-programming c++20


【解决方案1】:

您需要使用关键字typename 来判断dependent names std::remove_cv&lt;V&gt;::type 是一个类型。

return std::is_same<u_underlying, typename std::remove_cv<V>::type>::value;
//                                ^^^^^^^^

using 语句中,typename 自 C++20 以来不再需要。

在某些情况下,只有类型名称才能有效出现。在这些 在上下文中,假定从属限定名称命名一个类型并且没有 typename 为必填项:

  • ...

  • 出现在type-id 中的限定名称,其中最小的封闭type-id 是:

【讨论】:

  • 嗯,看来clang还是需要的。也许那是缺少的功能?
  • @Mikhail 我认为 clang 还没有实现新功能。
  • Clang 尚未实现,请参阅 cppreference 上的P0634R3
猜你喜欢
  • 2021-09-03
  • 2015-03-02
  • 2013-06-22
  • 2021-09-24
  • 2017-01-17
  • 1970-01-01
  • 1970-01-01
  • 2016-05-23
  • 1970-01-01
相关资源
最近更新 更多