【问题标题】:C++20 Concepts: out-of-line-definition fails with MSVC but not in GCC or clangC++20 概念:在 MSVC 中,行外定义失败,但在 GCC 或 clang 中没有
【发布时间】:2021-01-13 12:50:03
【问题描述】:

考虑一下这个小代码sn-p

namespace nsp
{
    template<typename T>
    concept Addable= requires(const T& a,const T& b)
    {
        {a + b} -> std::convertible_to<T>;
    };

    template<Addable T>
    struct C
    {
        C();
    };
}

template<nsp::Addable T>
nsp::C<T>::C() {};

如图所示here GCC (10.2) 和 clang (11.0) 接受代码,而 MSVC (x86 19.28) 拒绝它并显示错误消息:

error C3855: 'nsp::C<T>': template parameter 'T' is incompatible with the declaration. 

这是一个 MSVC 错误还是 GCC 和 clang 错误地接受它?或者,我是不是有些愚蠢?如果我将离线定义移到命名空间 nsp 中,它似乎也适用于 MSVC。看到这个example

【问题讨论】:

  • 我似乎在那个名称下找不到这个特定的语言功能,但你知道en.cppreference.com/w/cpp/compiler_support 的存在吗?
  • @YVbakker 叫做“概念”,根据链接页面,MSVC 只支持部分。
  • No compiler supports all C++20 features。有些功能适用于 MSVC,但不适用于 GCC。 MSVC 更新不如 GCC 频繁。另一方面,对 GCC 的一个常见抱怨是编译器在您的脚下更改的频率。
  • @Yksisarvinen 啊太棒了!我今天也学到了一些新东西
  • @Hack20 c++20 标准已经完成。我们应该开始学习和适应它。我根本不会认为这是“匆忙”。

标签: c++ c++20 c++-concepts


【解决方案1】:

这种行为是 MSVC 中可观察到的偏差,通常在模板和 SFINAE 的上下文中看到。当声明不合格时(由于位于同一名称空间中),MSVC 往往难以处理具有限定条件的模板的离线定义。我在处理 SFINAE 表单时经常遇到这种情况,而且现在concepts 似乎也一定会发生这种情况。

例如,MSVC 拒绝有效代码:

namespace nsp {

  template <typename T>
  using is_convertible_to_bool = std::is_convertible<T, bool>;

  template <typename T, std::enable_if_t<is_convertible_to_bool<T>::value,int> = 0>
  void example(const T& x);

} // namespace nsp

template <typename T, std::enable_if_t<nsp::is_convertible_to_bool<T>::value,int>>
void nsp::example(const T& x)
{

}

Live Example

但是,MSVC 将接受相同的代码,前提是您在 is_convertible_to_bool 上添加来自 namespace nsp 的资格:

  template <typename T, std::enable_if_t<nsp::is_convertible_to_bool<T>::value,int> = 0>
  //                                     ^~~~~ fixes it
  void example(const T& x);

Live example

同样,如果您更改 struct C 的定义以包含完全限定的概念名称,您的代码示例实际上可以工作:

    template<nsp::Addable T>
    //       ^~~~~
    //       Qualifying here fixes the failure in MSVC
    struct C
    {
        C();
    };

Live Example


我没有时间检查编译器正确的查找规则的标准(如果没有其他答案出现,稍后会这样做),但我的期望实际上是 MSVC 提供的不正确行为。基本名称查找应该在两个定义中选择相同的类型,因此代码应该格式正确。

【讨论】:

    猜你喜欢
    • 2021-09-22
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2021-04-02
    • 2020-12-14
    • 1970-01-01
    • 2021-12-17
    • 2020-09-24
    相关资源
    最近更新 更多